diff --git a/.circleci/config.yml b/.circleci/config.yml index 1784ba1e..e7916074 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,7 +36,7 @@ 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 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 gettext ccache wget gcc-multilib upx openssh-client - save_cache: key: v1-SRB2-APT paths: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7995034d..51f98707 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string. # Version change is fine. project(SRB2 - VERSION 1.1.0 + VERSION 1.2 LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) diff --git a/appveyor.yml b/appveyor.yml index 3d46cf6d..4ad24ee0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,145 +1,141 @@ -version: 1.1.0.{branch}-{build} -os: MinGW - -environment: - CC: ccache - CCACHE_CC: i686-w64-mingw32-gcc - CCACHE_CC_64: x86_64-w64-mingw32-gcc - WINDRES: windres - # c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead - MINGW_SDK: c:\msys64\mingw32 - # c:\msys64 x86_64 has gcc 8.2.0, so use c:\mingw-w64 7.3.0 instead - MINGW_SDK_64: C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64 - CFLAGS: -Wall -W -Werror -Wno-error=implicit-fallthrough -Wimplicit-fallthrough=3 -Wno-tautological-compare -Wno-error=suggest-attribute=noreturn - NASM_ZIP: nasm-2.12.01 - NASM_URL: http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip - UPX_ZIP: upx391w - UPX_URL: http://upx.sourceforge.net/download/upx391w.zip - CCACHE_EXE: ccache.exe - CCACHE_URL: http://alam.srb2.org/ccache.exe - CCACHE_COMPRESS: true - CCACHE_DIR: C:\Users\appveyor\.ccache - # Disable UPX by default. The user can override this in their Appveyor project settings - NOUPX: 1 - ############################## - # DEPLOYER VARIABLES - # DPL_ENABLED=1 builds installers for branch names starting with `deployer`. - # DPL_TAG_ENABLED=1 will also build installers for release tags. DPL_ENABLED=1 must also be set. - # Set these in the Appveyor project settings - ############################## - DPL_ENABLED: 0 - DPL_TAG_ENABLED: 0 - DPL_INSTALLER_NAME: srb2kart-v110 - # Asset handling is barebones vs. Travis Deployer. We operate on 7z only. - # Include the README files and the OpenGL batch in the main and patch archives. - # The x86/x64 archives contain the DLL binaries. - ASSET_ARCHIVE_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-assets.7z - ASSET_ARCHIVE_PATCH_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-patch-assets.7z - ASSET_ARCHIVE_X86_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-x86-assets.7z - ASSET_ARCHIVE_X64_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-x64-assets.7z - ASSET_ARCHIVE_OPTIONAL_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-optional-assets.7z - # This is overridden to 1 for release tag builds - ASSET_FILES_OPTIONAL_GET: 0 - # For patches, also include the X86/X64 DLLs. - PACKAGE_PATCH_DLL_GET: 0 - # Delete all asset downloads so they can be redownloaded - ASSET_CLEAN: 0 - -cache: -- nasm-2.12.01.zip -- upx391w.zip -- ccache.exe -- C:\Users\appveyor\.ccache -- C:\Users\appveyor\srb2_cache - -install: -- if [%CONFIGURATION%] == [SDL64] ( set "X86_64=1" ) -- if [%CONFIGURATION%] == [SDL64] ( set "CONFIGURATION=SDL" ) -- if [%CONFIGURATION%] == [DD64] ( set "X86_64=1" ) -- if [%CONFIGURATION%] == [DD64] ( set "CONFIGURATION=DD" ) -- if [%X86_64%] == [1] ( set "MINGW_SDK=%MINGW_SDK_64%" ) -- if [%X86_64%] == [1] ( set "CCACHE_CC=%CCACHE_CC_64%" ) - -- if not exist "%NASM_ZIP%.zip" appveyor DownloadFile "%NASM_URL%" -FileName "%NASM_ZIP%.zip" -- 7z x -y "%NASM_ZIP%.zip" -o%TMP% >null -- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%NASM_ZIP%" "%MINGW_SDK%\bin" nasm.exe || exit 0 - -- if not exist "%UPX_ZIP%.zip" appveyor DownloadFile "%UPX_URL%" -FileName "%UPX_ZIP%.zip" -- 7z x -y "%UPX_ZIP%.zip" -o%TMP% >null -- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%UPX_ZIP%" "%MINGW_SDK%\bin" upx.exe || exit 0 - -- if not exist "%CCACHE_EXE%" appveyor DownloadFile "%CCACHE_URL%" -FileName "%CCACHE_EXE%" -- ccache -M 99M -- xcopy /Y /V /I ccache.exe "%MINGW_SDK%\bin" - -configuration: -- SDL -- SDL64 -#- DD -#- DD64 - -matrix: - allow_failures: - - configuration: DD - - configuration: DD64 - -before_build: -- set "Path=%MINGW_SDK%\bin;%Path%" -- if [%X86_64%] == [1] ( x86_64-w64-mingw32-gcc --version ) else ( i686-w64-mingw32-gcc --version ) -- mingw32-make --version -- if not [%X86_64%] == [1] ( nasm -v ) -- if not [%NOUPX%] == [1] ( upx -V ) -- ccache -V -- ccache -s -- if [%NOUPX%] == [1] ( set "NOUPX=NOUPX=1" ) else ( set "NOUPX=" ) -- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 GCC72=1 NOOBJDUMP=1 %NOUPX%" -- if [%X86_64%] == [1] ( set "MINGW_FLAGS=MINGW64=1 X86_64=1" ) else ( set "MINGW_FLAGS=MINGW=1" ) -- set "SRB2_MFLAGS=%SRB2_MFLAGS% %MINGW_FLAGS% %CONFIGURATION%=1" - -build_script: -- cmd: mingw32-make.exe %SRB2_MFLAGS% clean -- cmd: mingw32-make.exe %SRB2_MFLAGS% ERRORMODE=1 -k - -after_build: -- if [%X86_64%] == [1] ( - set "BUILD_PATH=bin\Mingw64\Release" - ) else ( - set "BUILD_PATH=bin\Mingw\Release" - ) -- if [%X86_64%] == [1] ( set "CONFIGURATION=%CONFIGURATION%64" ) -- ccache -s -- cmd: git rev-parse --short %APPVEYOR_REPO_COMMIT%>%TMP%/gitshort.txt -- cmd: set /P GITSHORT=<%TMP%/gitshort.txt -- set BUILD_ARCHIVE=%APPVEYOR_REPO_BRANCH%-%GITSHORT%-%CONFIGURATION%.7z -- set BUILDSARCHIVE=%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%.7z -- cmd: 7z a %BUILD_ARCHIVE% %BUILD_PATH% -xr!.gitignore -- appveyor PushArtifact %BUILD_ARCHIVE% -- cmd: copy %BUILD_ARCHIVE% %BUILDSARCHIVE% -- appveyor PushArtifact %BUILDSARCHIVE% -############################## -# DEPLOYER SCRIPT -############################## -- if [%DPL_ENABLED%] == [1] ( call "deployer\appveyor\deployer.bat" ) - -test: off - -#deploy: -# - provider: FTP -# protocol: ftps -# host: -# secure: NsLJEPIBvmwCOj8Tg8RoRQ== -# username: -# secure: ejxi5mvk7oLYu7QtbYojajEPigMy0mokaKhuEVuDZcA= -# password: -# secure: Hbn6Uy3lT0YZ88yFJ3aW4w== -# folder: appveyor -# application: -# active_mode: false -# on: -# branch: master -# appveyor_repo_tag: true - - -on_finish: -#- cmd: echo xfreerdp /u:appveyor /cert-ignore +clipboard /v:: -#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +version: 1.2.{branch}-{build} +os: MinGW + +environment: + CC: ccache + CCACHE_CC: i686-w64-mingw32-gcc + CCACHE_CC_64: x86_64-w64-mingw32-gcc + WINDRES: windres + # c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead + MINGW_SDK: c:\msys64\mingw32 + # c:\msys64 x86_64 has gcc 8.2.0, so use c:\mingw-w64 7.3.0 instead + MINGW_SDK_64: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64 + CFLAGS: -Wall -W -Werror -Wno-error=implicit-fallthrough -Wimplicit-fallthrough=3 -Wno-tautological-compare -Wno-error=suggest-attribute=noreturn + NASM_ZIP: nasm-2.12.01 + NASM_URL: http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip + UPX_ZIP: upx391w + UPX_URL: http://upx.sourceforge.net/download/upx391w.zip + CCACHE_EXE: ccache.exe + CCACHE_URL: http://alam.srb2.org/ccache.exe + CCACHE_COMPRESS: true + CCACHE_DIR: C:\Users\appveyor\.ccache + # Disable UPX by default. The user can override this in their Appveyor project settings + NOUPX: 1 + ############################## + # DEPLOYER VARIABLES + # DPL_ENABLED=1 builds installers for branch names starting with `deployer`. + # DPL_TAG_ENABLED=1 will also build installers for release tags. DPL_ENABLED=1 must also be set. + # Set these in the Appveyor project settings + ############################## + DPL_ENABLED: 0 + DPL_TAG_ENABLED: 0 + DPL_INSTALLER_NAME: srb2kart-v12 + # Asset handling is barebones vs. Travis Deployer. We operate on 7z only. + # Include the README files and the OpenGL batch in the main and patch archives. + # The x86/x64 archives contain the DLL binaries. + ASSET_ARCHIVE_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-assets.7z + ASSET_ARCHIVE_PATCH_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-patch-assets.7z + ASSET_ARCHIVE_X86_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-x86-assets.7z + ASSET_ARCHIVE_X64_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-x64-assets.7z + ASSET_ARCHIVE_OPTIONAL_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-optional-assets.7z + # This is overridden to 1 for release tag builds + ASSET_FILES_OPTIONAL_GET: 0 + # For patches, also include the X86/X64 DLLs. + PACKAGE_PATCH_DLL_GET: 0 + # Delete all asset downloads so they can be redownloaded + ASSET_CLEAN: 0 + +cache: +- nasm-2.12.01.zip +- upx391w.zip +- ccache.exe +- C:\Users\appveyor\.ccache +- C:\Users\appveyor\srb2_cache + +install: +- if [%CONFIGURATION%] == [SDL64] ( set "X86_64=1" ) +- if [%CONFIGURATION%] == [SDL64] ( set "CONFIGURATION=SDL" ) +- if [%X86_64%] == [1] ( set "MINGW_SDK=%MINGW_SDK_64%" ) +- if [%X86_64%] == [1] ( set "CCACHE_CC=%CCACHE_CC_64%" ) + +- if not exist "%NASM_ZIP%.zip" appveyor DownloadFile "%NASM_URL%" -FileName "%NASM_ZIP%.zip" +- 7z x -y "%NASM_ZIP%.zip" -o%TMP% >null +- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%NASM_ZIP%" "%MINGW_SDK%\bin" nasm.exe || exit 0 + +- if not exist "%UPX_ZIP%.zip" appveyor DownloadFile "%UPX_URL%" -FileName "%UPX_ZIP%.zip" +- 7z x -y "%UPX_ZIP%.zip" -o%TMP% >null +- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%UPX_ZIP%" "%MINGW_SDK%\bin" upx.exe || exit 0 + +- if not exist "%CCACHE_EXE%" appveyor DownloadFile "%CCACHE_URL%" -FileName "%CCACHE_EXE%" +- ccache -M 99M +- xcopy /Y /V /I ccache.exe "%MINGW_SDK%\bin" + +configuration: +- SDL +#- SDL64 + +before_build: +- set "Path=%MINGW_SDK%\bin;%Path%" +- if [%X86_64%] == [1] ( x86_64-w64-mingw32-gcc --version ) else ( i686-w64-mingw32-gcc --version ) +- mingw32-make --version +- if not [%X86_64%] == [1] ( nasm -v ) +- if not [%NOUPX%] == [1] ( upx -V ) +- ccache -V +- ccache -s +- if [%NOUPX%] == [1] ( set "NOUPX=NOUPX=1" ) else ( set "NOUPX=" ) +- if defined [%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%] ( set "COMMIT=%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%" ) else ( set "COMMIT=%APPVEYOR_REPO_COMMIT%" ) +- cmd: git rev-parse --short %COMMIT%>%TMP%/gitshort.txt +- cmd: set /P GITSHORT=<%TMP%/gitshort.txt +# for pull requests, take the owner's name only, if this isn't the same repo of course +- set "REPO=%APPVEYOR_REPO_BRANCH%" +- if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [] ( if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [%APPVEYOR_REPO_NAME%] ( for /f "delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set "REPO=%%a-%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%" ) ) +- set "EXENAME=EXENAME=srb2win-%REPO%-%GITSHORT%.exe" +- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 NOOBJDUMP=1 %NOUPX% %EXENAME%" +- if [%X86_64%] == [1] ( set "MINGW_FLAGS=MINGW64=1 X86_64=1 GCC81=1" ) else ( set "MINGW_FLAGS=MINGW=1 GCC91=1" ) +- set "SRB2_MFLAGS=%SRB2_MFLAGS% %MINGW_FLAGS% %CONFIGURATION%=1" + +build_script: +- cmd: mingw32-make.exe %SRB2_MFLAGS% clean +- cmd: mingw32-make.exe %SRB2_MFLAGS% ERRORMODE=1 -k + +after_build: +- if [%X86_64%] == [1] ( + set "BUILD_PATH=bin\Mingw64\Release" + ) else ( + set "BUILD_PATH=bin\Mingw\Release" + ) +- if [%X86_64%] == [1] ( set "CONFIGURATION=%CONFIGURATION%64" ) +- ccache -s +- set BUILD_ARCHIVE=%REPO%-%GITSHORT%-%CONFIGURATION%.7z +- 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% +############################## +# DEPLOYER SCRIPT +############################## +- if [%DPL_ENABLED%] == [1] ( call "deployer\appveyor\deployer.bat" ) + +test: off + +#deploy: +# - provider: FTP +# protocol: ftps +# host: +# secure: NsLJEPIBvmwCOj8Tg8RoRQ== +# username: +# secure: ejxi5mvk7oLYu7QtbYojajEPigMy0mokaKhuEVuDZcA= +# password: +# secure: Hbn6Uy3lT0YZ88yFJ3aW4w== +# folder: appveyor +# application: +# active_mode: false +# on: +# branch: master +# appveyor_repo_tag: true + + +on_finish: +#- cmd: echo xfreerdp /u:appveyor /cert-ignore +clipboard /v:: +#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/debian-template/control b/debian-template/control index 6614d315..4db1d875 100644 --- a/debian-template/control +++ b/debian-template/control @@ -25,6 +25,7 @@ Depends: ${SHLIBS_DEPENDS}, ${MISC_DEPENDS}, libsdl2-mixer-2.0-0, zlib1g, libgme0, + libcurl4, 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/debian-template/source/options b/debian-template/source/options index 9532ff20..7829e297 100644 --- a/debian-template/source/options +++ b/debian-template/source/options @@ -2,7 +2,10 @@ tar-ignore = "assets/*.srb" tar-ignore = "assets/*.pk3" tar-ignore = "assets/*.dta" tar-ignore = "assets/*.wad" +<<<<<<< HEAD:debian-template/source/options tar-ignore = "assets/*.kart" +======= +>>>>>>> e251f9c230beda984cdcdea7e903d765f1c68f6f:debian-template/source/options tar-ignore = "assets/debian/${PACKAGE_NAME}-data/*" tar-ignore = "assets/debian/tmp/*" tar-ignore = "*.obj" diff --git a/libs/libgme.props b/libs/libgme.props new file mode 100644 index 00000000..209f6b9a --- /dev/null +++ b/libs/libgme.props @@ -0,0 +1,16 @@ + + + + + + $(SolutionDir)libs\gme\include;$(IncludePath) + $(SolutionDir)libs\gme\win32;$(LibraryPath) + $(SolutionDir)libs\gme\win64;$(LibraryPath) + + + + libgme.dll.a;%(AdditionalDependencies) + + + + \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f995d046..c0d673a6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -220,7 +220,7 @@ set(SRB2_CONFIG_HAVE_ZLIB ON CACHE BOOL "Enable zlib support.") set(SRB2_CONFIG_HAVE_GME ON CACHE BOOL "Enable GME support.") -set(SRB2_CONFIG_HAVE_GME ON CACHE BOOL +set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL "Enable curl support, used for downloading files via HTTP.") set(SRB2_CONFIG_HWRENDER ON CACHE BOOL "Enable hardware rendering through OpenGL.") @@ -398,9 +398,9 @@ if(${SRB2_CONFIG_HAVE_CURL}) set(CURL_FOUND ON) set(CURL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/curl) if(${SRB2_SYSTEM_BITS} EQUAL 64) - set(CURL_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/curl/lib32 -lcurl") - else() # 32-bit set(CURL_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/curl/lib64 -lcurl") + else() # 32-bit + set(CURL_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/curl/lib32 -lcurl") endif() else() find_package(CURL) @@ -436,7 +436,6 @@ if(${SRB2_CONFIG_HWRENDER}) ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_drv.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_glide.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_glob.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h diff --git a/src/Makefile b/src/Makefile index 98763603..75ea0de1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -753,8 +753,8 @@ ifdef SDL ifdef MINGW $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + command.h hardware/hw_data.h hardware/hw_defs.h hardware/hw_md2.h \ + hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h @@ -762,8 +762,8 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h else $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + command.h hardware/hw_data.h hardware/hw_defs.h hardware/hw_md2.h \ + hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h @@ -916,8 +916,8 @@ ifndef SDL ifndef NOHW $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + command.h hardware/hw_data.h hardware/hw_defs.h hardware/hw_md2.h \ + hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h @@ -925,8 +925,8 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + command.h hardware/hw_data.h hardware/hw_defs.h hardware/hw_md2.h \ + hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h @@ -934,8 +934,8 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \ $(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ + command.h hardware/hw_data.h hardware/hw_defs.h hardware/hw_md2.h \ + hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 8402e349..a3baeedd 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -7,11 +7,19 @@ # and other things # -ifdef GCC81 -GCC80=1 +ifdef GCC91 +GCC83=1 endif -ifdef GCC80 +ifdef GCC83 +GCC82=1 +endif + +ifdef GCC82 +GCC81=1 +endif + +ifdef GCC81 GCC72=1 endif @@ -186,6 +194,9 @@ ifndef GCC295 endif endif WFLAGS+=-Wformat-y2k +ifdef GCC71 +WFLAGS+=-Wno-error=format-overflow=2 +endif WFLAGS+=-Wformat-security ifndef GCC29 #WFLAGS+=-Winit-self @@ -222,9 +233,9 @@ endif ifdef GCC71 WFLAGS+=-Wno-error=implicit-fallthrough WFLAGS+=-Wno-implicit-fallthrough - WFLAGS+=-Wno-error=format-truncation + WFLAGS+=-Wno-format-truncation endif -ifdef GCC80 +ifdef GCC81 WFLAGS+=-Wno-error=format-overflow WFLAGS+=-Wno-error=stringop-truncation WFLAGS+=-Wno-error=stringop-overflow diff --git a/src/command.c b/src/command.c index 6d9c86d3..bd3a2243 100644 --- a/src/command.c +++ b/src/command.c @@ -56,7 +56,7 @@ static void CV_EnforceExecVersion(void); static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr); static boolean CV_Command(void); -static consvar_t *CV_FindVar(const char *name); +consvar_t *CV_FindVar(const char *name); static const char *CV_StringValue(const char *var_name); static consvar_t *consvar_vars; // list of registered console variables @@ -86,7 +86,7 @@ static boolean joyaxis_default[4] = {false,false,false,false}; static INT32 joyaxis_count[4] = {0,0,0,0}; #endif -#define COM_BUF_SIZE 8192 // command buffer size +#define COM_BUF_SIZE 0x4000 // command buffer size, 0x4000 = 16384 #define MAX_ALIAS_RECURSION 100 // max recursion allowed for aliases static INT32 com_wait; // one command per frame (for cmd sequences) @@ -532,7 +532,6 @@ static void COM_ExecuteString(char *ptext) { if (!stricmp(com_argv[0], cmd->name)) //case insensitive now that we have lower and uppercase! { - recursion = 0; cmd->function(); return; } @@ -544,7 +543,7 @@ static void COM_ExecuteString(char *ptext) if (!stricmp(com_argv[0], a->name)) { if (recursion > MAX_ALIAS_RECURSION) - { + { CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n")); recursion = 0; } @@ -586,8 +585,6 @@ static void COM_ExecuteString(char *ptext) } } - recursion = 0; - // check cvars // Hurdler: added at Ebola's request ;) // (don't flood the console in software mode with bad gr_xxx command) @@ -1027,7 +1024,7 @@ static const char *cv_null_string = ""; * \return Pointer to the variable if found, or NULL. * \sa CV_FindNetVar */ -static consvar_t *CV_FindVar(const char *name) +consvar_t *CV_FindVar(const char *name) { consvar_t *cvar; @@ -1307,8 +1304,7 @@ found: var->string = var->zstring = Z_StrDup(valstr); - if (var->flags & CV_PASSWORD); // Don't change value for password field - else if (override) + if (override) var->value = overrideval; else if (var->flags & CV_FLOAT) { diff --git a/src/command.h b/src/command.h index 6b5d513e..0880065b 100644 --- a/src/command.h +++ b/src/command.h @@ -98,8 +98,7 @@ typedef enum CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console // can only be set when we have the pointer to it // used on menus - CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on. - CV_PASSWORD = 4096 // Password field + CV_CHEAT = 2048 // Don't let this be used in multiplayer unless cheats are on. } cvflags_t; typedef struct CV_PossibleValue_s @@ -173,4 +172,7 @@ void CV_ResetCheatNetVars(void); boolean CV_IsSetToDefault(consvar_t *v); UINT8 CV_CheatsEnabled(void); +// Returns cvar by name. Exposed here for Lua. +consvar_t *CV_FindVar(const char *name); + #endif // __COMMAND_H__ diff --git a/src/config.h.in b/src/config.h.in index f3f8339f..a7a0be53 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -37,7 +37,7 @@ * Last updated 2015 / 05 / 03 - SRB2 v2.1.15 - srb2.srb * Last updated 2018 / 12 / 23 - SRB2 v2.1.22 - patch.dta * Last updated 2019 / 01 / 18 - Kart v1.0.2 - Main assets - * Last updated 2019 / 05 / 06 - Kart v1.1.0 - patch.kart + * Last updated 2020 / 05 / 09 - Kart v1.2 - patch.kart */ // Base SRB2 hashes @@ -52,7 +52,7 @@ #define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964" #define ASSET_HASH_MAPS_KART "1335cd064656aedca359cfbb5233ac4a" #ifdef USE_PATCH_KART -#define ASSET_HASH_PATCH_KART "7093231f2c3c1cca1a909a708be85d9a" +#define ASSET_HASH_PATCH_KART "2a556446ab428492110e7544841e1f42" #endif #endif diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 9ab9cd7a..8b401251 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -23,7 +23,6 @@ #include "d_net.h" #include "d_netfil.h" // fileneedednum #include "d_main.h" -#include "d_event.h" #include "g_game.h" #include "hu_stuff.h" #include "keys.h" @@ -71,8 +70,6 @@ // firstticstosend is used to optimize a condition // Normally maketic >= gametic > 0 -#define PREDICTIONQUEUE BACKUPTICS -#define PREDICTIONMASK (PREDICTIONQUEUE-1) #define MAX_REASONLENGTH 30 #define FORCECLOSE 0x8000 @@ -109,7 +106,7 @@ static tic_t firstticstosend; // min of the nettics static tic_t tictoclear = 0; // optimize d_clearticcmd static tic_t maketic; -static INT16 consistancy[BACKUPTICS]; +static INT16 consistancy[TICQUEUE]; // Resynching shit! static UINT32 resynch_score[MAXNETNODES]; // "score" for kicking -- if this gets too high then cfail kick @@ -163,7 +160,7 @@ typedef struct textcmdtic_s struct textcmdtic_s *next; } textcmdtic_t; -ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; +ticcmd_t netcmds[TICQUEUE][MAXPLAYERS]; static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; @@ -172,6 +169,8 @@ consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_httpsource = {"http_source", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n) { const size_t d = n / sizeof(ticcmd_t); @@ -208,21 +207,22 @@ UINT16 software_MAXPACKETLENGTH; /** Guesses the value of a tic from its lowest byte and from maketic * * \param low The lowest byte of the tic value + * \param basetic The last full tic value to compare against * \return The full tic value * */ -tic_t ExpandTics(INT32 low) +tic_t ExpandTics(INT32 low, tic_t basetic) { INT32 delta; - delta = low - (maketic & UINT8_MAX); + delta = low - (basetic & UINT8_MAX); if (delta >= -64 && delta <= 64) - return (maketic & ~UINT8_MAX) + low; + return (basetic & ~UINT8_MAX) + low; else if (delta > 64) - return (maketic & ~UINT8_MAX) - 256 + low; + return (basetic & ~UINT8_MAX) - 256 + low; else //if (delta < -64) - return (maketic & ~UINT8_MAX) + 256 + low; + return (basetic & ~UINT8_MAX) + 256 + low; } // ----------------------------------------------------------------- @@ -467,9 +467,9 @@ static void D_Clearticcmd(tic_t tic) D_FreeTextcmd(tic); for (i = 0; i < MAXPLAYERS; i++) - netcmds[tic%BACKUPTICS][i].angleturn = 0; + netcmds[tic%TICQUEUE][i].angleturn = 0; - DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); + DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%TICQUEUE)); } void D_ResetTiccmds(void) @@ -1102,22 +1102,21 @@ typedef enum CL_CONNECTED, CL_ABORTED, CL_ASKFULLFILELIST, - CL_ASKDOWNLOADFILES, - CL_WAITDOWNLOADFILESRESPONSE, - CL_CHALLENGE +#ifdef HAVE_CURL + CL_PREPAREHTTPFILES, + CL_DOWNLOADHTTPFILES, +#endif } cl_mode_t; static void GetPackets(void); static cl_mode_t cl_mode = CL_SEARCHING; -static boolean cl_needsdownload = false; -static UINT16 cl_lastcheckedfilecount = 0; -static UINT8 cl_challengenum = 0; -static UINT8 cl_challengequestion[MD5_LEN+1]; -static char cl_challengepassword[65]; -static UINT8 cl_challengeanswer[MD5_LEN+1]; -static UINT8 cl_challengeattempted = 0; +#ifdef HAVE_CURL +char http_source[MAX_MIRROR_LENGTH]; +#endif + +static UINT16 cl_lastcheckedfilecount = 0; // used for full file list // Player name send/load @@ -1154,7 +1153,6 @@ static void CV_LoadPlayerNames(UINT8 **p) } #ifdef CLIENT_LOADINGSCREEN -static UINT32 SL_SearchServer(INT32 node); // // CL_DrawConnectionStatus @@ -1172,49 +1170,22 @@ static inline void CL_DrawConnectionStatus(void) M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort"); - if (cl_mode != CL_DOWNLOADFILES) + if (cl_mode != CL_DOWNLOADFILES +#ifdef HAVE_CURL + && cl_mode != CL_DOWNLOADHTTPFILES +#endif + ) { INT32 i, animtime = ((ccstime / 4) & 15) + 16; UINT8 palstart = (cl_mode == CL_SEARCHING) ? 128 : 160; // 15 pal entries total. const char *cltext; - if (cl_mode != CL_CHALLENGE) - for (i = 0; i < 16; ++i) - V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); + for (i = 0; i < 16; ++i) + V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); switch (cl_mode) { - case CL_CHALLENGE: - { - char asterisks[33]; - size_t sl = min(32, strlen(cl_challengepassword)); - UINT32 serverid; - - memset(asterisks, '*', sl); - memset(asterisks+sl, 0, 33-sl); - - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_MONOSPACE|V_ALLOWLOWERCASE, asterisks); - V_DrawFixedPatch((BASEVIDWIDTH/2) << FRACBITS, (BASEVIDHEIGHT/2) << FRACBITS, FRACUNIT, 0, W_CachePatchName("BSRVLOCK", PU_CACHE), NULL); - - serverid = SL_SearchServer(servernode); - - if (serverid == UINT32_MAX) - { - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT/2-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, V_REDMAP, M_GetText("This server is password protected.")); - } - else - { - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT/2-8, 32, 3); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, V_REDMAP, M_GetText("This server,")); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2+8, V_ALLOWLOWERCASE, serverlist[serverid].info.servername); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2+16, V_REDMAP, M_GetText("is password protected.")); - } - - cltext = M_GetText(cl_challengeattempted ? "Incorrect password. Please try again." : "Please enter the server password."); - } - break; #ifdef JOININGAME case CL_DOWNLOADSAVEGAME: if (lastfilenum != -1) @@ -1237,9 +1208,11 @@ static inline void CL_DrawConnectionStatus(void) case CL_WAITJOINRESPONSE: cltext = M_GetText("Requesting to join..."); break; - case CL_ASKDOWNLOADFILES: - case CL_WAITDOWNLOADFILESRESPONSE: +#ifdef HAVE_CURL + case CL_PREPAREHTTPFILES: cltext = M_GetText("Waiting to download files..."); + break; +#endif default: cltext = M_GetText("Connecting to server..."); break; @@ -1323,22 +1296,31 @@ static boolean CL_SendJoin(void) localplayers++; netbuffer->u.clientcfg.localplayers = localplayers; + netbuffer->u.clientcfg._255 = 255; + netbuffer->u.clientcfg.packetversion = PACKETVERSION; netbuffer->u.clientcfg.version = VERSION; netbuffer->u.clientcfg.subversion = SUBVERSION; - netbuffer->u.clientcfg.needsdownload = cl_needsdownload; - netbuffer->u.clientcfg.challengenum = cl_challengenum; - memcpy(netbuffer->u.clientcfg.challengeanswer, cl_challengeanswer, MD5_LEN); + strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application); - return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); + return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak)); } static void SV_SendServerInfo(INT32 node, tic_t servertime) { UINT8 *p; +#ifdef HAVE_CURL + size_t mirror_length; + const char *httpurl = cv_httpsource.string; +#endif netbuffer->packettype = PT_SERVERINFO; + netbuffer->u.serverinfo._255 = 255; + netbuffer->u.serverinfo.packetversion = PACKETVERSION; netbuffer->u.serverinfo.version = VERSION; netbuffer->u.serverinfo.subversion = SUBVERSION; + strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION, + sizeof netbuffer->u.serverinfo.application); // return back the time value so client can compute their ping netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); @@ -1351,10 +1333,10 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.kartvars = (UINT8) ( (cv_kartspeed.value & SV_SPEEDMASK) | - (dedicated ? SV_DEDICATED : 0) | - (D_IsJoinPasswordOn() ? SV_PASSWORD : 0) + (dedicated ? SV_DEDICATED : 0) ); + strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, MAXSERVERNAME); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); @@ -1367,6 +1349,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.iszone = 0; memset(netbuffer->u.serverinfo.maptitle, 0, 33); + memset(netbuffer->u.serverinfo.httpsource, 0, MAX_MIRROR_LENGTH); if (!(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU) && mapheaderinfo[gamemap-1]->lvlttl[0]) { @@ -1418,6 +1401,18 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.actnum = 0; //mapheaderinfo[gamemap-1]->actnum +#ifdef HAVE_CURL + mirror_length = strlen(httpurl); + if (mirror_length > MAX_MIRROR_LENGTH) + mirror_length = MAX_MIRROR_LENGTH; + + if (snprintf(netbuffer->u.serverinfo.httpsource, mirror_length+1, "%s", httpurl) < 0) + // If there's an encoding error, send nothing, we accept that the above may be truncated + strncpy(netbuffer->u.serverinfo.httpsource, "", mirror_length); + + netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0'; +#endif + p = PutFileNeeded(0); HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); @@ -1747,7 +1742,7 @@ static void CL_LoadReceivedSavegame(void) save_p = NULL; if (unlink(tmpsave) == -1) CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); - consistancy[gametic%BACKUPTICS] = Consistancy(); + consistancy[gametic%TICQUEUE] = Consistancy(); CON_ToggleOff(); } #endif @@ -1804,12 +1799,21 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) if (serverlistcount >= MAXSERVERLIST) return; // list full + if (info->_255 != 255) + return;/* old packet format */ + + if (info->packetversion != PACKETVERSION) + return;/* old new packet format */ + if (info->version != VERSION) return; // Not same version. if (info->subversion != SUBVERSION) return; // Close, but no cigar. + if (strcmp(info->application, SRB2APPLICATION)) + return;/* that's a different mod */ + i = serverlistcount++; } @@ -1993,23 +1997,35 @@ static boolean CL_FinishedFileList(void) { // must download something // can we, though? - if (!CL_CheckDownloadable()) // nope! +#ifdef HAVE_CURL + if (http_source[0] == '\0' || curl_failedwebdownload) +#endif { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You cannot connect to this server\n" - "because you cannot download the files\n" - "that you are missing from the server.\n\n" - "See the console or log file for\n" - "more details.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } + if (!CL_CheckDownloadable()) // nope! + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You cannot connect to this server\n" + "because you cannot download the files\n" + "that you are missing from the server.\n\n" + "See the console or log file for\n" + "more details.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } - cl_mode = CL_ASKDOWNLOADFILES; + if (CL_SendRequestFile()) + cl_mode = CL_DOWNLOADFILES; + } +#ifdef HAVE_CURL + else + { + cl_mode = CL_PREPAREHTTPFILES; + } +#endif } return true; } @@ -2056,6 +2072,16 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) if (client) { +#ifdef HAVE_CURL + if (serverlist[i].info.httpsource[0]) + strncpy(http_source, serverlist[i].info.httpsource, MAX_MIRROR_LENGTH); + else + http_source[0] = '\0'; +#else + if (serverlist[i].info.httpsource[0]) + CONS_Printf("We received a http url from the server, however it will not be used as this build lacks curl support (%s)\n", serverlist[i].info.httpsource); +#endif + D_ParseFileneeded(serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded, 0); if (serverlist[i].info.kartvars & SV_LOTSOFADDONS) { @@ -2131,6 +2157,53 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } break; +#ifdef HAVE_CURL + case CL_PREPAREHTTPFILES: + if (http_source[0]) + { + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) + curl_transfers++; + + cl_mode = CL_DOWNLOADHTTPFILES; + } + break; + + case CL_DOWNLOADHTTPFILES: + waitmore = false; + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) + { + if (!curl_running) + CURLPrepareFile(http_source, i); + waitmore = true; + break; + } + + if (curl_running) + CURLGetFile(); + + if (waitmore) + break; // exit the case + + if (curl_failedwebdownload && !curl_transfers) + { + if (!CL_FinishedFileList()) + break; + + CONS_Printf("One or more files failed to download, falling back to internal downloader\n"); + if (CL_SendRequestFile()) + { + cl_mode = CL_DOWNLOADFILES; + break; + } + } + + if (!curl_transfers) + cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now + + break; +#endif case CL_DOWNLOADFILES: waitmore = false; for (i = 0; i < fileneedednum; i++) @@ -2147,7 +2220,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic /* FALLTHRU */ case CL_ASKJOIN: - cl_needsdownload = false; CL_LoadServerFiles(); #ifdef JOININGAME // prepare structures to save the file @@ -2156,23 +2228,9 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic CL_PrepareDownloadSaveGame(tmpsave); #endif if (CL_SendJoin()) - { - *asksent = I_GetTime(); cl_mode = CL_WAITJOINRESPONSE; - } break; - case CL_ASKDOWNLOADFILES: - cl_needsdownload = true; - - if (CL_SendJoin()) - { - *asksent = I_GetTime(); - cl_mode = CL_WAITDOWNLOADFILESRESPONSE; - } - break; - - #ifdef JOININGAME case CL_DOWNLOADSAVEGAME: // At this state, the first (and only) needed file is the gamestate @@ -2186,19 +2244,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic break; #endif - case CL_CHALLENGE: - (*asksent) = I_GetTime() - NEWTICRATE; // Send password immediately upon entering - break; - case CL_WAITJOINRESPONSE: - case CL_WAITDOWNLOADFILESRESPONSE: - if (*asksent + NEWTICRATE < I_GetTime() && CL_SendJoin()) - { - *asksent = I_GetTime(); - } - - break; - case CL_CONNECTED: default: break; @@ -2216,15 +2262,21 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic // Call it only once by tic if (*oldtic != I_GetTime()) { - I_OsPolling(); - D_ProcessEvents(); - if (gamestate != GS_WAITINGPLAYERS) - return false; - // why are these here? this is for servers, we're a client - //if (key == 's' && server) - // doomcom->numnodes = (INT16)pnumnodes; - //SV_FileSendTicker(); + INT32 key; + + I_OsPolling(); + key = I_GetKey(); + // Only ESC and non-keyboard keys abort connection + if (key == KEY_ESCAPE || key >= KEY_MOUSE1) + { + CONS_Printf(M_GetText("Network game synchronization aborted.\n")); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + + return false; + } *oldtic = I_GetTime(); #ifdef CLIENT_LOADINGSCREEN @@ -2248,71 +2300,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic return true; } -boolean CL_Responder(event_t *ev) -{ - size_t len; - INT32 ch; - - if (!(client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)) - return false; // Don't do anything outside of the connection screen - - if (ev->type != ev_keydown) - return false; - - ch = (INT32)ev->data1; - - // Only ESC and non-keyboard keys abort connection - if (ch == KEY_ESCAPE || ch >= KEY_MOUSE1) - { - CONS_Printf(M_GetText("Network game synchronization aborted.\n")); - //M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - return true; - } - - if (cl_mode != CL_CHALLENGE) - return false; - - if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART]) - || ch == ' ') // Allow spaces, of course - { - len = strlen(cl_challengepassword); - if (len < 64) - { - cl_challengepassword[len+1] = 0; - cl_challengepassword[len] = CON_ShiftChar(ch); - } - - cl_challengeattempted = 0; - } - else if (ch == KEY_BACKSPACE) - { - len = strlen(cl_challengepassword); - - if (len > 0) - cl_challengepassword[len-1] = 0; - - cl_challengeattempted = 0; - } - else if (ch == KEY_ENTER) - { - netgame = true; - multiplayer = true; - -#ifndef NONET - SL_ClearServerList(servernode); -#endif - cl_mode = CL_SEARCHING; - - D_ComputeChallengeAnswer(cl_challengequestion, cl_challengepassword, cl_challengeanswer); - cl_challengeattempted = 1; - } - - return true; -} - /** Use adaptive send using net_bandwidth and stat.sendbytes * * \todo Better description... @@ -2332,7 +2319,6 @@ static void CL_ConnectToServer(void) #endif cl_mode = CL_SEARCHING; - cl_challengenum = 0; #ifdef CLIENT_LOADINGSCREEN lastfilenum = -1; @@ -2381,14 +2367,12 @@ static void CL_ConnectToServer(void) gametypestr = Gametype_Names[num]; if (gametypestr) CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); - CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, - serverlist[i].info.version%100, serverlist[i].info.subversion); + CONS_Printf(M_GetText("Version: %d.%d\n"), + serverlist[i].info.version, serverlist[i].info.subversion); } SL_ClearServerList(servernode); #endif - cl_challengeattempted = 0; - do { // If the connection was aborted for some reason, leave @@ -2801,6 +2785,13 @@ void CL_Reset(void) fileneedednum = 0; memset(fileneeded, 0, sizeof(fileneeded)); +#ifdef HAVE_CURL + curl_failedwebdownload = false; + curl_transfers = 0; + curl_running = false; + http_source[0] = '\0'; +#endif + // D_StartTitle should get done now, but the calling function will handle it } @@ -3285,8 +3276,8 @@ static void Got_RemovePlayer(UINT8 **p, INT32 playernum); // called one time at init void D_ClientServerInit(void) { - DEBFILE(va("- - -== SRB2Kart v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n", - VERSION/100, VERSION%100, SUBVERSION)); + DEBFILE(va("- - -== SRB2Kart v%d.%d "VERSIONSTRING" debugfile ==- - -\n", + VERSION, SUBVERSION)); #ifndef NONET COM_AddCommand("getplayernum", Command_GetPlayerNum); @@ -3320,9 +3311,6 @@ void D_ClientServerInit(void) gametic = 0; localgametic = 0; - memset(cl_challengequestion, 0x00, MD5_LEN+1); - memset(cl_challengeanswer, 0x00, MD5_LEN+1); - // do not send anything before the real begin SV_StopServer(); SV_ResetServer(); @@ -3714,7 +3702,7 @@ void SV_StopServer(void) localtextcmd3[0] = 0; localtextcmd4[0] = 0; - for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) + for (i = firstticstosend; i < firstticstosend + TICQUEUE; i++) D_Clearticcmd(i); consoleplayer = 0; @@ -3778,9 +3766,15 @@ static void HandleConnect(SINT8 node) if (bannednode && bannednode[node]) SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server")); + else if (netbuffer->u.clientcfg._255 != 255 || + netbuffer->u.clientcfg.packetversion != PACKETVERSION) + SV_SendRefuse(node, "Incompatible packet formats."); + else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application)) + SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible."); else if (netbuffer->u.clientcfg.version != VERSION || netbuffer->u.clientcfg.subversion != SUBVERSION) - SV_SendRefuse(node, va(M_GetText("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION)); + SV_SendRefuse(node, va(M_GetText("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d)"), VERSION, SUBVERSION)); else if (!cv_allownewplayer.value && node) SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment")); else if (D_NumPlayers() >= maxplayers) @@ -3797,33 +3791,6 @@ static void HandleConnect(SINT8 node) boolean newnode = false; #endif - if (node != servernode && !nodeingame[node] && D_IsJoinPasswordOn()) - { - // Ensure node sent the correct password challenge - boolean passed = false; - - if (netbuffer->u.clientcfg.challengenum && D_VerifyJoinPasswordChallenge(netbuffer->u.clientcfg.challengenum, netbuffer->u.clientcfg.challengeanswer)) - passed = true; - - if (!passed) - { - D_MakeJoinPasswordChallenge(&netbuffer->u.joinchallenge.challengenum, netbuffer->u.joinchallenge.question); - - netbuffer->packettype = PT_JOINCHALLENGE; - HSendPacket(node, true, 0, sizeof(joinchallenge_pak)); - Net_CloseConnection(node); - - return; - } - } - - if (netbuffer->u.clientcfg.needsdownload) - { - netbuffer->packettype = PT_DOWNLOADFILESOKAY; - HSendPacket(node, true, 0, 0); - return; - } - // client authorised to join nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); if (!nodeingame[node]) @@ -3922,6 +3889,8 @@ static void HandleServerInfo(SINT8 node) const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; + netbuffer->u.serverinfo.application + [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; netbuffer->u.serverinfo.gametype = (UINT8)((netbuffer->u.serverinfo.gametype == VANILLA_GT_MATCH) ? GT_MATCH : GT_RACE); SL_InsertServer(&netbuffer->u.serverinfo, node); @@ -4021,43 +3990,6 @@ static void HandlePacketFromAwayNode(SINT8 node) Net_CloseConnection(node); break; - case PT_JOINCHALLENGE: - if (server && serverrunning) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - if (cl_mode == CL_WAITJOINRESPONSE || cl_mode == CL_WAITDOWNLOADFILESRESPONSE) - { - cl_challengenum = netbuffer->u.joinchallenge.challengenum; - memcpy(cl_challengequestion, netbuffer->u.joinchallenge.question, 16); - - Net_CloseConnection(node|FORCECLOSE); // Don't need to stay connected while challenging - - cl_mode = CL_CHALLENGE; - - switch (cl_challengeattempted) - { - case 2: - // We already sent a correct password, so throw it back up again. - D_ComputeChallengeAnswer(cl_challengequestion, cl_challengepassword, cl_challengeanswer); - cl_mode = CL_ASKJOIN; - break; - - case 1: - // We entered the wrong password! - S_StartSound(NULL, sfx_s26d); - break; - - default: - // First entry to the password screen. - S_StartSound(NULL, sfx_s224); - break; - } - } - break; - case PT_SERVERREFUSE: // Negative response of client join request if (server && serverrunning) { // But wait I thought I'm the server? @@ -4086,41 +4018,6 @@ static void HandlePacketFromAwayNode(SINT8 node) } break; - case PT_DOWNLOADFILESOKAY: - if (server && serverrunning) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - - SERVERONLY - - // This should've already been checked, but just to be safe... - if (!CL_CheckDownloadable()) - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You cannot connect to this server\n" - "because you cannot download the files\n" - "that you are missing from the server.\n\n" - "See the console or log file for\n" - "more details.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - break; - } - - if (cl_challengeattempted == 1) // Successful password noise. - S_StartSound(NULL, sfx_s221); - - cl_challengeattempted = 2; - CONS_Printf("trying to download\n"); - if (CL_SendRequestFile()) - cl_mode = CL_DOWNLOADFILES; - break; - case PT_SERVERCFG: // Positive response of client join request { INT32 j; @@ -4136,9 +4033,6 @@ static void HandlePacketFromAwayNode(SINT8 node) if (cl_mode != CL_WAITJOINRESPONSE) break; - if (cl_challengeattempted == 1) // Successful password noise. - S_StartSound(NULL, sfx_s221); - if (client) { maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); @@ -4247,9 +4141,9 @@ static void HandlePacketFromAwayNode(SINT8 node) */ static boolean CheckForSpeedHacks(UINT8 p) { - if (netcmds[maketic%BACKUPTICS][p].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].forwardmove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][p].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].sidemove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][p].driftturn > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].driftturn < -KART_FULLTURN) + if (netcmds[maketic%TICQUEUE][p].forwardmove > MAXPLMOVE || netcmds[maketic%TICQUEUE][p].forwardmove < -MAXPLMOVE + || netcmds[maketic%TICQUEUE][p].sidemove > MAXPLMOVE || netcmds[maketic%TICQUEUE][p].sidemove < -MAXPLMOVE + || netcmds[maketic%TICQUEUE][p].driftturn > KART_FULLTURN || netcmds[maketic%TICQUEUE][p].driftturn < -KART_FULLTURN) { XBOXSTATIC char buf[2]; CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), playernode[p]); @@ -4296,7 +4190,7 @@ FILESTAMP case PT_RESYNCHGET: if (client) break; - SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot); + SV_AcknowledgeResynchAck(node, netbuffer->u.resynchgot); break; case PT_CLIENTCMD: case PT_CLIENT2CMD: @@ -4317,8 +4211,8 @@ FILESTAMP // To save bytes, only the low byte of tic numbers are sent // Use ExpandTics to figure out what the rest of the bytes are - realstart = ExpandTics(netbuffer->u.clientpak.client_tic); - realend = ExpandTics(netbuffer->u.clientpak.resendfrom); + realstart = ExpandTics(netbuffer->u.clientpak.client_tic, nettics[node]); + realend = ExpandTics(netbuffer->u.clientpak.resendfrom, nettics[node]); if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS || netbuffer->packettype == PT_CLIENT3MIS || netbuffer->packettype == PT_CLIENT4MIS @@ -4355,7 +4249,7 @@ FILESTAMP break; // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][netconsole], &netbuffer->u.clientpak.cmd, 1); // Check ticcmd for "speed hacks" if (CheckForSpeedHacks((UINT8)netconsole)) @@ -4367,7 +4261,7 @@ FILESTAMP || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) && (nodetoplayer2[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer2[node])) @@ -4378,7 +4272,7 @@ FILESTAMP || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) && (nodetoplayer3[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer3[node]], + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer3[node]], &netbuffer->u.client3pak.cmd3, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer3[node])) @@ -4388,7 +4282,7 @@ FILESTAMP if ((netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS) && (nodetoplayer4[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer4[node]], + G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer4[node]], &netbuffer->u.client4pak.cmd4, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer4[node])) @@ -4403,8 +4297,8 @@ FILESTAMP break; } // Check player consistancy during the level - if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)) + if (realstart <= gametic && realstart > gametic - TICQUEUE+1 && gamestate == GS_LEVEL + && consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)) { SV_RequireResynch(node); @@ -4413,10 +4307,10 @@ FILESTAMP if (cv_blamecfail.value) CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), netconsole+1, player_names[netconsole], - consistancy[realstart%BACKUPTICS], + consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy)); DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], + netconsole, realstart, consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy))); break; } @@ -4428,7 +4322,7 @@ FILESTAMP buf[1] = KICK_MSG_CON_FAIL; SendNetXCmd(XD_KICK, &buf, 2); DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], + netconsole, realstart, consistancy[realstart%TICQUEUE], SHORT(netbuffer->u.clientpak.consistancy))); break; } @@ -4503,10 +4397,10 @@ FILESTAMP // search a tic that have enougth space in the ticcmd while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) - && tic < firstticstosend + BACKUPTICS) + && tic < firstticstosend + TICQUEUE) tic++; - if (tic >= firstticstosend + BACKUPTICS) + if (tic >= firstticstosend + TICQUEUE) { DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), @@ -4614,7 +4508,7 @@ FILESTAMP break; } - realstart = ExpandTics(netbuffer->u.serverpak.starttic); + realstart = ExpandTics(netbuffer->u.serverpak.starttic, maketic); realend = realstart + netbuffer->u.serverpak.numtics; if (!txtpak) @@ -4636,7 +4530,7 @@ FILESTAMP D_Clearticcmd(i); // copy the tics - pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, + pak = G_ScpyTiccmd(netcmds[i%TICQUEUE], pak, netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); // copy the textcmds @@ -4963,6 +4857,20 @@ static void CL_SendClientKeepAlive(void) HSendPacket(servernode, false, 0, 0); } +static void SV_SendServerKeepAlive(void) +{ + INT32 n; + + for (n = 1; n < MAXNETNODES; n++) + { + if (nodeingame[n]) + { + netbuffer->packettype = PT_BASICKEEPALIVE; + HSendPacket(n, false, 0, 0); + } + } +} + // send the client packet to the server static void CL_SendClientCmd(void) { @@ -4991,7 +4899,7 @@ static void CL_SendClientCmd(void) { packetsize = sizeof (clientcmd_pak); G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); - netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); + netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%TICQUEUE]); if (splitscreen || botingame) // Send a special packet with 2 cmd for splitscreen { @@ -5078,20 +4986,23 @@ static void SV_SendTics(void) for (n = 1; n < MAXNETNODES; n++) if (nodeingame[n]) { - lasttictosend = maketic; - // assert supposedtics[n]>=nettics[n] realfirsttic = supposedtics[n]; - if (realfirsttic >= maketic) + lasttictosend = maketic; + + if (lasttictosend - nettics[n] >= BACKUPTICS) + lasttictosend = nettics[n] + BACKUPTICS-1; + + if (realfirsttic >= lasttictosend) { // well we have sent all tics we will so use extrabandwidth // to resent packet that are supposed lost (this is necessary since lost // packet detection work when we have received packet with firsttic > neededtic // (getpacket servertics case) DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", - n, maketic, supposedtics[n], nettics[n])); + n, lasttictosend, supposedtics[n], nettics[n])); realfirsttic = nettics[n]; - if (realfirsttic >= maketic || (I_GetTime() + n)&3) + if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) // all tic are ok continue; DEBFILE(va("Sent %d anyway\n", realfirsttic)); @@ -5141,7 +5052,7 @@ static void SV_SendTics(void) for (i = realfirsttic; i < lasttictosend; i++) { - bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); + bufpos = G_DcpyTiccmd(bufpos, netcmds[i%TICQUEUE], doomcom->numslots * sizeof (ticcmd_t)); } // add textcmds @@ -5206,7 +5117,7 @@ static void Local_Maketic(INT32 realtics) void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) { tic_t tic; - UINT8 numadjust = 0; + UINT16 numadjust = 0; (void)x; (void)y; @@ -5217,16 +5128,16 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) for (tic = server ? maketic : (neededtic - 1); tic >= gametic; tic--) { - if (numadjust++ == BACKUPTICS) + if (numadjust++ == TICQUEUE) { DEBFILE(va("SV_SpawnPlayer: All netcmds for player %d adjusted!\n", playernum)); // We already adjusted them all, waste of time doing the same thing over and over // This shouldn't happen normally though, either gametic was 0 (which is handled now anyway) - // or maketic >= gametic + BACKUPTICS + // or maketic >= gametic + TICQUEUE // -- Monster Iestyn 16/01/18 break; } - netcmds[tic%BACKUPTICS][playernum].angleturn = (INT16)((angle>>16) | TICCMD_RECEIVED); + netcmds[tic%TICQUEUE][playernum].angleturn = (INT16)((angle>>16) | TICCMD_RECEIVED); if (!tic) // failsafe for gametic == 0 -- Monster Iestyn 16/01/18 break; @@ -5242,7 +5153,7 @@ static void SV_Maketic(void) if (playerpernode[j]) { INT32 player = nodetoplayer[j]; - if ((netcmds[maketic%BACKUPTICS][player].angleturn & TICCMD_RECEIVED) == 0) + if ((netcmds[maketic%TICQUEUE][player].angleturn & TICCMD_RECEIVED) == 0) { // we didn't receive this tic INT32 i; @@ -5257,8 +5168,8 @@ static void SV_Maketic(void) else if (i == 1) player = nodetoplayer2[j]; else if (i == 2) player = nodetoplayer3[j]; else if (i == 3) player = nodetoplayer4[j]; - netcmds[maketic%BACKUPTICS][player] = netcmds[(maketic-1)%BACKUPTICS][player]; - netcmds[maketic%BACKUPTICS][player].angleturn &= ~TICCMD_RECEIVED; + netcmds[maketic%TICQUEUE][player] = netcmds[(maketic-1)%TICQUEUE][player]; + netcmds[maketic%TICQUEUE][player].angleturn &= ~TICCMD_RECEIVED; } } } @@ -5336,7 +5247,7 @@ void TryRunTics(tic_t realtics) G_Ticker((gametic % NEWTICRATERATIO) == 0); ExtraDataTicker(); gametic++; - consistancy[gametic%BACKUPTICS] = Consistancy(); + consistancy[gametic%TICQUEUE] = Consistancy(); // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) @@ -5415,6 +5326,8 @@ static inline void PingUpdate(void) //make the ping packet and clear server data for next one for (i = 0; i < MAXPLAYERS; i++) { + //CONS_Printf("player %d - total pings: %d\n", i, realpingtable[i]); + netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; //server takes a snapshot of the real ping for display. //otherwise, pings fluctuate a lot and would be odd to look at. @@ -5445,7 +5358,7 @@ static void UpdatePingTable(void) // update node latency values so we can take an average later. for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) - realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); + realpingtable[i] += (INT32)(GetLag(playernode[i]) * (1000.00f/TICRATE)); // TicsToMilliseconds can't handle pings over 1000ms lol pingmeasurecount++; } } @@ -5475,9 +5388,6 @@ void NetKeepAlive(void) UpdatePingTable(); - if (server) - CL_SendClientKeepAlive(); - // Sryder: What is FILESTAMP??? FILESTAMP GetPackets(); @@ -5491,6 +5401,11 @@ FILESTAMP CL_SendClientKeepAlive(); // No need to check for resynch because we aren't running any tics } + else + { + SV_SendServerKeepAlive(); + } + // No else because no tics are being run and we can't resynch during this Net_AckTicker(); @@ -5569,8 +5484,8 @@ FILESTAMP // Do not make tics while resynching if (counts != -666) { - if (maketic + counts >= firstticstosend + BACKUPTICS) - counts = firstticstosend+BACKUPTICS-maketic-1; + if (maketic + counts >= firstticstosend + TICQUEUE) + counts = firstticstosend+TICQUEUE-maketic-1; for (i = 0; i < counts; i++) SV_Maketic(); // Create missed tics and increment maketic @@ -5621,3 +5536,59 @@ tic_t GetLag(INT32 node) { return gametic - nettics[node]; } + +#define REWIND_POINT_INTERVAL 4*TICRATE + 16 +rewind_t *rewindhead; + +void CL_ClearRewinds(void) +{ + rewind_t *head; + while ((head = rewindhead)) + { + rewindhead = rewindhead->next; + free(head); + } +} + +rewind_t *CL_SaveRewindPoint(size_t demopos) +{ + rewind_t *rewind; + + if (rewindhead && rewindhead->leveltime + REWIND_POINT_INTERVAL > leveltime) + return NULL; + + rewind = (rewind_t *)malloc(sizeof (rewind_t)); + if (!rewind) + return NULL; + + save_p = rewind->savebuffer; + P_SaveNetGame(); + rewind->leveltime = leveltime; + rewind->next = rewindhead; + rewind->demopos = demopos; + rewindhead = rewind; + + return rewind; +} + +rewind_t *CL_RewindToTime(tic_t time) +{ + rewind_t *rewind; + + while (rewindhead && rewindhead->leveltime > time) + { + rewind = rewindhead->next; + free(rewindhead); + rewindhead = rewind; + } + + if (!rewindhead) + return NULL; + + save_p = rewindhead->savebuffer; + P_LoadNetGame(); + wipegamestate = gamestate; // No fading back in! + timeinmap = leveltime; + + return rewindhead; +} diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 294d88d7..a872b02e 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -13,14 +13,19 @@ #ifndef __D_CLISRV__ #define __D_CLISRV__ -#include "d_event.h" #include "d_ticcmd.h" +#include "d_net.h" #include "d_netcmd.h" #include "tables.h" #include "d_player.h" #include "mserv.h" -#include "md5.h" +/* +The 'packet version' is used to distinguish packet formats. +This version is independent of VERSION and SUBVERSION. Different +applications may follow different packet versions. +*/ +#define PACKETVERSION 0 // Network play related stuff. // There is a data struct that stores network @@ -30,7 +35,9 @@ // SOME numpty changed all the gametype constants and it fell out of sync with vanilla and now we have to pretend to be vanilla when talking to the master server... #define VANILLA_GT_RACE 2 -#if VERSION < 210 +// Woah, what do these numbers mean? 200 refers to SRB2 2.0, 246 refers to +// SRB2Riders. Both use the old 2.0 gametype numbers. +#if VERSION == 200 || VERSION == 246 #define VANILLA_GT_MATCH 1 #else #define VANILLA_GT_MATCH 3 @@ -38,6 +45,7 @@ // Networking and tick handling related. #define BACKUPTICS 32 +#define TICQUEUE 512 // more than enough for most timeouts.... #define MAXTEXTCMD 256 // // Packet structure @@ -77,9 +85,6 @@ typedef enum PT_CLIENT4MIS, PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called - PT_JOINCHALLENGE, // You must give a password to joinnnnn - PT_DOWNLOADFILESOKAY, // You can download files from the server.... - PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL // allows HSendPacket(*, true, *, *) to return false. // In addition, this packet can't occupy all the available slots. @@ -343,32 +348,37 @@ typedef struct { #pragma warning(default : 4200) #endif +#define MAXAPPLICATION 16 + typedef struct { + UINT8 _255;/* see serverinfo_pak */ + UINT8 packetversion; + char application[MAXAPPLICATION]; UINT8 version; // Different versions don't work UINT8 subversion; // Contains build version - UINT8 localplayers; - UINT8 needsdownload; - UINT8 challengenum; // Non-zero if trying to join with a password attempt - UINT8 challengeanswer[MD5_LEN]; // Join challenge + UINT8 localplayers; // number of splitscreen players + UINT8 mode; } ATTRPACK clientconfig_pak; -typedef struct -{ - UINT8 challengenum; // Number to send back in join attempt - UINT8 question[MD5_LEN]; // Challenge data to be manipulated and answered with -} ATTRPACK joinchallenge_pak; - -#define SV_SPEEDMASK 0x03 -#define SV_LOTSOFADDONS 0x20 -#define SV_DEDICATED 0x40 -#define SV_PASSWORD 0x80 +#define SV_SPEEDMASK 0x03 // used to send kartspeed +#define SV_DEDICATED 0x40 // server is dedicated +#define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil #define MAXSERVERNAME 32 #define MAXFILENEEDED 915 +#define MAX_MIRROR_LENGTH 256 // This packet is too large typedef struct { + /* + In the old packet, 'version' is the first field. Now that field is set + to 255 always, so older versions won't be confused with the new + versions or vice-versa. + */ + UINT8 _255; + UINT8 packetversion; + char application[MAXAPPLICATION]; UINT8 version; UINT8 subversion; UINT8 numberofplayer; @@ -378,7 +388,6 @@ typedef struct UINT8 cheatsenabled; UINT8 kartvars; // Previously isdedicated, now appropriated for our own nefarious purposes UINT8 fileneedednum; - SINT8 adminplayer; tic_t time; tic_t leveltime; char servername[MAXSERVERNAME]; @@ -387,6 +396,7 @@ typedef struct unsigned char mapmd5[16]; UINT8 actnum; UINT8 iszone; + char httpsource[MAX_MIRROR_LENGTH]; // HTTP URL to download from, always defined for compatibility UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK serverinfo_pak; @@ -464,7 +474,6 @@ typedef struct UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) filetx_pak filetxpak; // 139 bytes clientconfig_pak clientcfg; // 153 bytes - joinchallenge_pak joinchallenge; // 17 bytes serverinfo_pak serverinfo; // 1024 bytes serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes @@ -481,7 +490,7 @@ typedef struct #pragma pack() #endif -#define MAXSERVERLIST 64 // Depends only on the display +#define MAXSERVERLIST (MAXNETNODES-1) typedef struct { SINT8 node; @@ -494,7 +503,7 @@ extern INT32 mapchangepending; // Points inside doomcom extern doomdata_t *netbuffer; - +extern consvar_t cv_httpsource; extern consvar_t cv_showjoinaddress; extern consvar_t cv_playbackspeed; @@ -546,7 +555,7 @@ extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; // Used in d_net, the only dependence -tic_t ExpandTics(INT32 low); +tic_t ExpandTics(INT32 low, tic_t basetic); void D_ClientServerInit(void); // Initialise the other field @@ -572,7 +581,6 @@ void CL_ClearPlayer(INT32 playernum); void CL_RemovePlayer(INT32 playernum, INT32 reason); void CL_QueryServerList(msg_server_t *list); void CL_UpdateServerList(boolean internetsearch, INT32 room); -boolean CL_Responder(event_t *ev); // Is there a game running boolean Playing(void); @@ -605,4 +613,19 @@ UINT8 GetFreeXCmdSize(void); extern UINT8 hu_resynching; extern UINT8 hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player + +typedef struct rewind_s { + UINT8 savebuffer[(768*1024)]; + tic_t leveltime; + size_t demopos; + + ticcmd_t oldcmd[MAXPLAYERS]; + mobj_t oldghost[MAXPLAYERS]; + + struct rewind_s *next; +} rewind_t; + +void CL_ClearRewinds(void); +rewind_t *CL_SaveRewindPoint(size_t demopos); +rewind_t *CL_RewindToTime(tic_t time); #endif diff --git a/src/d_main.c b/src/d_main.c index c1b2ef17..b5fd3098 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -181,6 +181,7 @@ void D_PostEvent_end(void) {}; #endif // modifier keys +// Now handled in I_OsPolling UINT8 shiftdown = 0; // 0x1 left, 0x2 right UINT8 ctrldown = 0; // 0x1 left, 0x2 right UINT8 altdown = 0; // 0x1 left, 0x2 right @@ -229,16 +230,10 @@ void D_ProcessEvents(void) { ev = &events[eventtail]; - // Set global shift/ctrl/alt down variables - D_ModifierKeyResponder(ev); // never eats events - // Screenshots over everything so that they can be taken anywhere. if (M_ScreenshotResponder(ev)) continue; // ate the event - if (CL_Responder(ev)) - continue; - if (gameaction == ga_nothing && gamestate == GS_TITLESCREEN) { if (cht_Responder(ev)) @@ -265,6 +260,11 @@ void D_ProcessEvents(void) if (eaten) continue; // menu ate the event + // Demo input: + if (demo.playback) + if (M_DemoResponder(ev)) + continue; // demo ate the event + // console input #ifdef HAVE_THREADS I_lock_mutex(&con_mutex); @@ -299,29 +299,29 @@ static void D_Display(void) INT32 wipedefindex = 0; UINT8 i; - if (dedicated) - return; - - if (nodrawers) - return; // for comparative timing/profiling - - // check for change of screen size (video mode) - if (setmodeneeded && !wipe) - SCR_SetMode(); // change video mode - - if (vid.recalc) - SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() - - // change the view size if needed - if (setsizeneeded) + if (!dedicated) { - R_ExecuteSetViewSize(); - forcerefresh = true; // force background redraw - } + if (nodrawers) + return; // for comparative timing/profiling + + // check for change of screen size (video mode) + if (setmodeneeded && !wipe) + SCR_SetMode(); // change video mode - // draw buffered stuff to screen - // Used only by linux GGI version - I_UpdateNoBlit(); + if (vid.recalc) + SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() + + // change the view size if needed + if (setsizeneeded) + { + R_ExecuteSetViewSize(); + forcerefresh = true; // force background redraw + } + + // draw buffered stuff to screen + // Used only by linux GGI version + I_UpdateNoBlit(); + } // save the current screen if about to wipe wipe = (gamestate != wipegamestate); @@ -339,7 +339,7 @@ static void D_Display(void) wipedefindex = wipe_multinter_toblack; } - if (rendermode != render_none) + if (!dedicated) { // Fade to black first if (gamestate != GS_LEVEL // fades to black on its own timing, always @@ -359,8 +359,16 @@ static void D_Display(void) F_WipeStartScreen(); } + else //dedicated servers + { + F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK); + wipegamestate = gamestate; + } } + if (dedicated) //bail out after wipe logic + return; + // do buffered drawing switch (gamestate) { @@ -470,7 +478,7 @@ static void D_Display(void) { if (i > 0) // Splitscreen-specific { - switch (i) + switch (i) { case 1: if (splitscreen > 1) @@ -498,7 +506,7 @@ static void D_Display(void) break; } - + topleft = screens[0] + viewwindowy*vid.width + viewwindowx; } @@ -642,9 +650,6 @@ void D_SRB2Loop(void) // Pushing of + parameters is now done back in D_SRB2Main, not here. - CONS_Printf("I_StartupKeyboard()...\n"); - I_StartupKeyboard(); - #ifdef _WINDOWS CONS_Printf("I_StartupMouse()...\n"); I_DoStartupMouse(); @@ -1330,6 +1335,14 @@ void D_SRB2Main(void) CONS_Printf("I_StartupGraphics()...\n"); I_StartupGraphics(); +#ifdef HWRENDER + if (rendermode == render_opengl) + { + for (i = 0; i < numwadfiles; i++) + HWR_LoadShaders(i, (wadfiles[i]->type == RET_PK3)); + } +#endif + //--------------------------------------------------------- CONSOLE // setup loading screen SCR_Startup(); diff --git a/src/d_net.c b/src/d_net.c index 94b11d51..3b1bad87 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -805,9 +805,6 @@ static const char *packettypename[NUMPACKETTYPE] = "CLIENT4MIS", "BASICKEEPALIVE", - "JOINCHALLENGE", - "DOWNLOADFILESOKAY", - "FILEFRAGMENT", "TEXTCMD", "TEXTCMD2", @@ -833,7 +830,7 @@ static void DebugPrintpacket(const char *header) break; case PT_CLIENTJOIN: fprintf(debugfile, " number %d mode %d\n", netbuffer->u.clientcfg.localplayers, - netbuffer->u.clientcfg.needsdownload); + netbuffer->u.clientcfg.mode); break; case PT_SERVERTICS: { @@ -842,7 +839,7 @@ static void DebugPrintpacket(const char *header) size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - cmd; fprintf(debugfile, " firsttic %u ply %d tics %d ntxtcmd %s\n ", - (UINT32)ExpandTics(serverpak->starttic), serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd)); + (UINT32)serverpak->starttic, serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd)); /// \todo Display more readable information about net commands fprintfstringnewline((char *)cmd, ntxtcmd); /*fprintfstring((char *)cmd, 3); @@ -865,8 +862,8 @@ static void DebugPrintpacket(const char *header) case PT_NODEKEEPALIVE: case PT_NODEKEEPALIVEMIS: fprintf(debugfile, " tic %4u resendfrom %u\n", - (UINT32)ExpandTics(netbuffer->u.clientpak.client_tic), - (UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom)); + (UINT32)netbuffer->u.clientpak.client_tic, + (UINT32)netbuffer->u.clientpak.resendfrom); break; case PT_BASICKEEPALIVE: fprintf(debugfile, " keep alive\n"); diff --git a/src/d_net.h b/src/d_net.h index eb657eec..30de2991 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -19,7 +19,7 @@ #define __D_NET__ // Max computers in a game -#define MAXNETNODES (MAXPLAYERS+4) +#define MAXNETNODES 64 #define BROADCASTADDR MAXNETNODES #define NETSPLITSCREEN // Kart's splitscreen netgame feature diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7dff1231..7d94d2ed 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -172,7 +172,6 @@ static void Got_Verification(UINT8 **cp, INT32 playernum); static void Got_Removal(UINT8 **cp, INT32 playernum); static void Command_Verify_f(void); static void Command_RemoveAdmin_f(void); -static void Command_ChangeJoinPassword_f(void); static void Command_MotD_f(void); static void Got_MotD_f(UINT8 **cp, INT32 playernum); @@ -554,8 +553,6 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_PICKVOTE, Got_PickVotecmd); // Remote Administration - CV_RegisterVar(&cv_dummyjoinpassword); - COM_AddCommand("joinpassword", Command_ChangeJoinPassword_f); COM_AddCommand("password", Command_Changepassword_f); RegisterNetXCmd(XD_LOGIN, Got_Login); COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin @@ -686,6 +683,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_noticedownload); CV_RegisterVar(&cv_downloadspeed); + CV_RegisterVar(&cv_httpsource); #ifndef NONET CV_RegisterVar(&cv_allownewplayer); #ifdef VANILLAJOINNEXTROUND @@ -2040,6 +2038,9 @@ static void Command_View_f(void) return; } + if (demo.freecam) + return; + displayplayerp = &displayplayers[viewnum-1]; if (COM_Argc() > 1)/* switch to player */ @@ -2688,11 +2689,17 @@ static void Command_Pause(void) if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer))) { - if (!paused && (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS))) + if (!paused && (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS))) { CONS_Printf(M_GetText("You can't pause here.\n")); return; } + else if (modeattacking) // in time attack, pausing restarts the map + { + M_ModeAttackRetry(0); // directly call from m_menu; + return; + } + SendNetXCmd(XD_PAUSE, &buf, 2); } else @@ -2769,6 +2776,12 @@ static void Command_Respawn(void) return; } + if (players[consoleplayer].mo && (players[consoleplayer].kartstuff[k_spinouttimer] || spbplace == players[consoleplayer].kartstuff[k_position])) // KART: Nice try, but no, you won't be cheesing spb anymore (x2) + { + CONS_Printf(M_GetText("Nice try.\n")); + return; + } + /*if (!G_RaceGametype()) // srb2kart: not necessary, respawning makes you lose a bumper in battle, so it's not desirable to use as a way to escape a hit { CONS_Printf(M_GetText("You may only use this in co-op, race, and competition!\n")); @@ -2791,7 +2804,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum) INT32 respawnplayer = READINT32(*cp); // You can't respawn someone else. Nice try, there. - if (respawnplayer != playernum) // srb2kart: "|| (!G_RaceGametype())" + if (respawnplayer != playernum || players[respawnplayer].kartstuff[k_spinouttimer] || spbplace == players[respawnplayer].kartstuff[k_position]) // srb2kart: "|| (!G_RaceGametype())" { CONS_Alert(CONS_WARNING, M_GetText("Illegal respawn command received from %s\n"), player_names[playernum]); if (server) @@ -3956,131 +3969,6 @@ static void Got_Removal(UINT8 **cp, INT32 playernum) CONS_Printf(M_GetText("You are no longer a server administrator.\n")); } -// Join password stuff -consvar_t cv_dummyjoinpassword = {"dummyjoinpassword", "", CV_HIDEN|CV_NOSHOWHELP|CV_PASSWORD, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; - -#define NUMJOINCHALLENGES 32 -static UINT8 joinpassmd5[MD5_LEN+1]; -boolean joinpasswordset = false; -static UINT8 joinpasschallenges[NUMJOINCHALLENGES][MD5_LEN]; -static tic_t joinpasschallengeson[NUMJOINCHALLENGES]; - -boolean D_IsJoinPasswordOn(void) -{ - return joinpasswordset; -} - -static inline void GetChallengeAnswer(UINT8 *question, UINT8 *passwordmd5, UINT8 *answer) -{ - D_MD5PasswordPass(question, MD5_LEN, (char *) passwordmd5, answer); -} - -void D_ComputeChallengeAnswer(UINT8 *question, const char *pw, UINT8 *answer) -{ - static UINT8 passwordmd5[MD5_LEN+1]; - - memset(passwordmd5, 0x00, MD5_LEN+1); - D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &passwordmd5); - GetChallengeAnswer(question, passwordmd5, answer); -} - -void D_SetJoinPassword(const char *pw) -{ - memset(joinpassmd5, 0x00, MD5_LEN+1); - D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &joinpassmd5); - joinpasswordset = true; -} - -boolean D_VerifyJoinPasswordChallenge(UINT8 num, UINT8 *answer) -{ - boolean passed = false; - - num %= NUMJOINCHALLENGES; - - //@TODO use a constant-time memcmp.... - if (joinpasschallengeson[num] > 0 && memcmp(answer, joinpasschallenges[num], MD5_LEN) == 0) - passed = true; - - // Wipe and reset the challenge so that it can't be tried against again, as a small measure against brute-force attacks. - memset(joinpasschallenges[num], 0x00, MD5_LEN); - joinpasschallengeson[num] = 0; - - return passed; -} - -void D_MakeJoinPasswordChallenge(UINT8 *num, UINT8 *question) -{ - size_t i; - - for (i = 0; i < NUMJOINCHALLENGES; i++) - { - (*num) = M_RandomKey(NUMJOINCHALLENGES); - - if (joinpasschallengeson[(*num)] == 0) - break; - } - - if (joinpasschallengeson[(*num)] > 0) - { - // Ugh, all challenges are (probably) taken. Let's find the oldest one and overwrite it. - tic_t oldesttic = INT32_MAX; - - for (i = 0; i < NUMJOINCHALLENGES; i++) - { - if (joinpasschallengeson[i] < oldesttic) - { - (*num) = i; - oldesttic = joinpasschallengeson[i]; - } - } - } - - joinpasschallengeson[(*num)] = I_GetTime(); - - memset(question, 0x00, MD5_LEN); - for (i = 0; i < MD5_LEN; i++) - question[i] = M_RandomByte(); - - // Store the answer in memory. What was the question again? - GetChallengeAnswer(question, joinpassmd5, joinpasschallenges[(*num)]); - - // This ensures that num is always non-zero and will be valid when used for the answer - if ((*num) == 0) - (*num) = NUMJOINCHALLENGES; -} - -// Remote Administration -static void Command_ChangeJoinPassword_f(void) -{ -#ifdef NOMD5 - // If we have no MD5 support then completely disable XD_LOGIN responses for security. - CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n"); -#else - if (client) // cannot change remotely - { - CONS_Printf(M_GetText("Only the server can use this.\n")); - return; - } - - if (COM_Argc() != 2) - { - CONS_Printf(M_GetText("joinpassword : set a password to join the server\nUse -remove to disable the password.\n")); - return; - } - - if (strcmp(COM_Argv(1), "-remove") == 0) - { - joinpasswordset = false; - CONS_Printf(M_GetText("Join password removed.\n")); - } - else - { - D_SetJoinPassword(COM_Argv(1)); - CONS_Printf(M_GetText("Join password set.\n")); - } -#endif -} - static void Command_MotD_f(void) { size_t i, j; @@ -5325,11 +5213,11 @@ static void Fishcake_OnChange(void) static void Command_Isgamemodified_f(void) { if (majormods) - CONS_Printf("The game has been modified with major add-ons, so you cannot play Record Attack.\n"); + CONS_Printf("The game has been modified with major addons, so you cannot play Record Attack.\n"); else if (savemoddata) - CONS_Printf("The game has been modified with an add-on with its own save data, so you can play Record Attack and earn medals.\n"); + CONS_Printf("The game has been modified with an addon with its own save data, so you can play Record Attack and earn medals.\n"); else if (modifiedgame) - CONS_Printf("The game has been modified with only minor add-ons. You can play Record Attack, earn medals and unlock extras.\n"); + CONS_Printf("The game has been modified with only minor addons. You can play Record Attack, earn medals and unlock extras.\n"); else CONS_Printf("The game has not been modified. You can play Record Attack, earn medals and unlock extras.\n"); } diff --git a/src/d_netcmd.h b/src/d_netcmd.h index e6c327ab..2d8e5705 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -246,14 +246,6 @@ void RemoveAdminPlayer(INT32 playernum); void ItemFinder_OnChange(void); void D_SetPassword(const char *pw); -extern consvar_t cv_dummyjoinpassword; -extern boolean joinpasswordset; -boolean D_IsJoinPasswordOn(void); -void D_ComputeChallengeAnswer(UINT8 *question, const char *pw, UINT8 *answer); -void D_SetJoinPassword(const char *pw); -boolean D_VerifyJoinPasswordChallenge(UINT8 num, UINT8 *answer); -void D_MakeJoinPasswordChallenge(UINT8 *num, UINT8 *question); - // used for the player setup menu UINT8 CanChangeSkin(INT32 playernum); diff --git a/src/d_netfil.c b/src/d_netfil.c index 76b66836..821d2a5b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -42,6 +42,10 @@ #include #endif +#ifdef HAVE_CURL +#include "curl/curl.h" +#endif + #include "doomdef.h" #include "doomstat.h" #include "d_main.h" @@ -65,6 +69,11 @@ // Prototypes static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid); +#ifdef HAVE_CURL +size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream); +int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); +#endif + // Sender structure typedef struct filetx_s { @@ -101,6 +110,22 @@ char downloaddir[512] = "DOWNLOAD"; INT32 lastfilenum = -1; #endif +#ifdef HAVE_CURL +static CURL *http_handle; +static CURLM *multi_handle; +boolean curl_running = false; +boolean curl_failedwebdownload = false; +static double curl_dlnow; +static double curl_dltotal; +static time_t curl_starttime; +INT32 curl_transfers = 0; +static int curl_runninghandles = 0; +static UINT32 curl_origfilesize; +static UINT32 curl_origtotalfilesize; +static char *curl_realname = NULL; +fileneeded_t *curl_curfile = NULL; +#endif + /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. @@ -238,10 +263,10 @@ boolean CL_CheckDownloadable(void) { CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10); - if (fileneeded[i].status == FS_NOTFOUND) - CONS_Printf(M_GetText(" not found, md5: ")); - else if (fileneeded[i].status == FS_MD5SUMBAD) + if (fileneeded[i].status == FS_MD5SUMBAD) CONS_Printf(M_GetText(" wrong version, md5: ")); + else + CONS_Printf(M_GetText(" not found, md5: ")); { INT32 j; @@ -296,7 +321,7 @@ boolean CL_SendRequestFile(void) netbuffer->packettype = PT_REQUESTFILE; p = (char *)netbuffer->u.textcmd; for (i = 0; i < fileneedednum; i++) - if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) + if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)) { totalfreespaceneeded += fileneeded[i].totalsize; nameonly(fileneeded[i].filename); @@ -1015,3 +1040,153 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found } + +#ifdef HAVE_CURL +size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t written; + written = fwrite(ptr, size, nmemb, stream); + return written; +} + +int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) +{ + (void)clientp; + (void)ultotal; + (void)ulnow; // Function prototype requires these but we won't use, so just discard + curl_dlnow = dlnow; + curl_dltotal = dltotal; + getbytes = curl_dlnow / (time(NULL) - curl_starttime); // To-do: Make this more accurate??? + return 0; +} + +void CURLPrepareFile(const char* url, int dfilenum) +{ +#ifdef PARANOIA + if (M_CheckParm("-nodownload")) + I_Error("Attempted to download files in -nodownload mode"); +#endif + + curl_global_init(CURL_GLOBAL_ALL); + + http_handle = curl_easy_init(); + multi_handle = curl_multi_init(); + + if (http_handle && multi_handle) + { + I_mkdir(downloaddir, 0755); + + curl_curfile = &fileneeded[dfilenum]; + curl_realname = curl_curfile->filename; + nameonly(curl_realname); + + curl_origfilesize = curl_curfile->currentsize; + curl_origtotalfilesize = curl_curfile->totalsize; + + curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s", url, curl_realname)); + + // Only allow HTTP and HTTPS + curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); + + curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents. + + // Follow a redirect request, if sent by the server. + curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L); + + curl_easy_setopt(http_handle, CURLOPT_FAILONERROR, 1L); + + CONS_Printf("Downloading %s from %s\n", curl_realname, url); + + strcatbf(curl_curfile->filename, downloaddir, "/"); + curl_curfile->file = fopen(curl_curfile->filename, "wb"); + curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, curl_curfile->file); + curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, curlwrite_data); + curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(http_handle, CURLOPT_PROGRESSFUNCTION, curlprogress_callback); + + curl_curfile->status = FS_DOWNLOADING; + lastfilenum = dfilenum; + curl_multi_add_handle(multi_handle, http_handle); + + curl_multi_perform(multi_handle, &curl_runninghandles); + curl_starttime = time(NULL); + curl_running = true; + } +} + +void CURLGetFile(void) +{ + CURLMcode mc; /* return code used by curl_multi_wait() */ + CURLcode easyres; /* Return from easy interface */ + int numfds; + CURLMsg *m; /* for picking up messages with the transfer status */ + CURL *e; + int msgs_left; /* how many messages are left */ + const char *easy_handle_error; + long response_code = 0; + + if (curl_runninghandles) + { + curl_multi_perform(multi_handle, &curl_runninghandles); + + /* wait for activity, timeout or "nothing" */ + mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds); + + if (mc != CURLM_OK) + { + CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc); + return; + } + curl_curfile->currentsize = curl_dlnow; + curl_curfile->totalsize = curl_dltotal; + } + + /* See how the transfers went */ + while ((m = curl_multi_info_read(multi_handle, &msgs_left))) + { + if (m && (m->msg == CURLMSG_DONE)) + { + e = m->easy_handle; + easyres = m->data.result; + if (easyres != CURLE_OK) + { + if (easyres == CURLE_HTTP_RETURNED_ERROR) + curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code); + + easy_handle_error = (response_code) ? va("HTTP reponse code %ld", response_code) : curl_easy_strerror(easyres); + curl_curfile->status = FS_FALLBACK; + curl_curfile->currentsize = curl_origfilesize; + curl_curfile->totalsize = curl_origtotalfilesize; + curl_failedwebdownload = true; + fclose(curl_curfile->file); + remove(curl_curfile->filename); + curl_curfile->file = NULL; + //nameonly(curl_curfile->filename); + nameonly(curl_realname); + CONS_Printf(M_GetText("Failed to download %s (%s)\n"), curl_realname, easy_handle_error); + } + else + { + nameonly(curl_realname); + CONS_Printf(M_GetText("Finished downloading %s\n"), curl_realname); + curl_curfile->status = FS_FOUND; + fclose(curl_curfile->file); + } + + curl_running = false; + curl_transfers--; + curl_multi_remove_handle(multi_handle, e); + curl_easy_cleanup(e); + + if (!curl_transfers) + break; + } + } + + if (!curl_transfers) + { + curl_multi_cleanup(multi_handle); + curl_global_cleanup(); + } +} +#endif diff --git a/src/d_netfil.h b/src/d_netfil.h index 2f033331..f37df371 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -30,7 +30,8 @@ typedef enum FS_REQUESTED, FS_DOWNLOADING, FS_OPEN, // Is opened and used in w_wad - FS_MD5SUMBAD + FS_MD5SUMBAD, + FS_FALLBACK, // HTTP failed } filestatus_t; typedef struct @@ -53,6 +54,12 @@ extern char downloaddir[512]; extern INT32 lastfilenum; #endif +#ifdef HAVE_CURL +extern boolean curl_failedwebdownload; +extern boolean curl_running; +extern INT32 curl_transfers; +#endif + UINT8 *PutFileNeeded(UINT16 firstfile); void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile); void CL_PrepareDownloadSaveGame(const char *tmpsave); @@ -83,4 +90,9 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum); void nameonly(char *s); size_t nameonlylength(const char *s); +#ifdef HAVE_CURL +void CURLPrepareFile(const char* url, int dfilenum); +void CURLGetFile(void); +#endif + #endif // __D_NETFIL__ diff --git a/src/dehacked.c b/src/dehacked.c index b311a860..96d82fff 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -42,10 +42,6 @@ #include "r_draw.h" // translation colormap consts (for lua) #endif -#ifdef HWRENDER -#include "hardware/hw_light.h" -#endif - #ifdef PC_DOS #include // for snprintf //int snprintf(char *str, size_t n, const char *fmt, ...); @@ -335,21 +331,6 @@ static INT32 searchvalue(const char *s) } } -#ifdef HWRENDER -static float searchfvalue(const char *s) -{ - while (s[0] != '=' && s[0]) - s++; - if (s[0] == '=') - return (float)atof(&s[1]); - else - { - deh_warning("No value found"); - return 0; - } -} -#endif - // These are for clearing all of various things static void clear_conditionsets(void) { @@ -854,128 +835,6 @@ static void readthing(MYFILE *f, INT32 num) Z_Free(s); } -#ifdef HWRENDER -static void readlight(MYFILE *f, INT32 num) -{ - char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - char *word; - char *tmp; - INT32 value; - float fvalue; - - do - { - if (myfgets(s, MAXLINELEN, f)) - { - if (s[0] == '\n') - break; - - tmp = strchr(s, '#'); - if (tmp) - *tmp = '\0'; - if (s == tmp) - continue; // Skip comment lines, but don't break. - - fvalue = searchfvalue(s); - value = searchvalue(s); - - word = strtok(s, " "); - if (word) - strupr(word); - else - break; - - if (fastcmp(word, "TYPE")) - { - DEH_WriteUndoline(word, va("%d", lspr[num].type), UNDO_NONE); - lspr[num].type = (UINT16)value; - } - else if (fastcmp(word, "OFFSETX")) - { - DEH_WriteUndoline(word, va("%f", lspr[num].light_xoffset), UNDO_NONE); - lspr[num].light_xoffset = fvalue; - } - else if (fastcmp(word, "OFFSETY")) - { - DEH_WriteUndoline(word, va("%f", lspr[num].light_yoffset), UNDO_NONE); - lspr[num].light_yoffset = fvalue; - } - else if (fastcmp(word, "CORONACOLOR")) - { - DEH_WriteUndoline(word, va("%u", lspr[num].corona_color), UNDO_NONE); - lspr[num].corona_color = value; - } - else if (fastcmp(word, "CORONARADIUS")) - { - DEH_WriteUndoline(word, va("%f", lspr[num].corona_radius), UNDO_NONE); - lspr[num].corona_radius = fvalue; - } - else if (fastcmp(word, "DYNAMICCOLOR")) - { - DEH_WriteUndoline(word, va("%u", lspr[num].dynamic_color), UNDO_NONE); - lspr[num].dynamic_color = value; - } - else if (fastcmp(word, "DYNAMICRADIUS")) - { - DEH_WriteUndoline(word, va("%f", lspr[num].dynamic_radius), UNDO_NONE); - lspr[num].dynamic_radius = fvalue; - - /// \note Update the sqrradius! unnecessary? - lspr[num].dynamic_sqrradius = fvalue * fvalue; - } - else - deh_warning("Light %d: unknown word '%s'", num, word); - } - } while (!myfeof(f)); // finish when the line is empty - - Z_Free(s); -} - -static void readspritelight(MYFILE *f, INT32 num) -{ - char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - char *word; - char *tmp; - INT32 value; - - do - { - if (myfgets(s, MAXLINELEN, f)) - { - if (s[0] == '\n') - break; - - tmp = strchr(s, '#'); - if (tmp) - *tmp = '\0'; - if (s == tmp) - continue; // Skip comment lines, but don't break. - - value = searchvalue(s); - - word = strtok(s, " "); - if (word) - strupr(word); - else - break; - - if (fastcmp(word, "LIGHTTYPE")) - { - INT32 oldvar; - for (oldvar = 0; t_lspr[num] != &lspr[oldvar]; oldvar++) - ; - DEH_WriteUndoline(word, va("%d", oldvar), UNDO_NONE); - t_lspr[num] = &lspr[value]; - } - else - deh_warning("Sprite %d: unknown word '%s'", num, word); - } - } while (!myfeof(f)); // finish when the line is empty - - Z_Free(s); -} -#endif // HWRENDER - static const struct { const char *name; const UINT16 flag; @@ -3513,37 +3372,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) readAnimTex(f, i); // This is not a major mod. }*/ - else if (fastcmp(word, "LIGHT")) - { -#ifdef HWRENDER - // TODO: Read lights by name - if (i > 0 && i < NUMLIGHTS) - readlight(f, i); - else - { - deh_warning("Light number %d out of range (1 - %d)", i, NUMLIGHTS-1); - ignorelines(f); - } - DEH_WriteUndoline(word, word2, UNDO_HEADER); - // This is not a major mod. -#endif - } - else if (fastcmp(word, "SPRITE")) - { -#ifdef HWRENDER - if (i == 0 && word2[0] != '0') // If word2 isn't a number - i = get_sprite(word2); // find a sprite by name - if (i < NUMSPRITES && i >= 0) - readspritelight(f, i); - else - { - deh_warning("Sprite number %d out of range (0 - %d)", i, NUMSPRITES-1); - ignorelines(f); - } - DEH_WriteUndoline(word, word2, UNDO_HEADER); - // This is not a major mod. -#endif - } else if (fastcmp(word, "LEVEL")) { // Support using the actual map name, @@ -7391,7 +7219,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Castle Eggman Scenery "MT_CHAIN", // CEZ Chain - "MT_FLAME", // Flame (has corona) + "MT_FLAME", // Flame "MT_EGGSTATUE", // Eggman Statue "MT_MACEPOINT", // Mace rotation point "MT_SWINGMACEPOINT", // Mace swinging point @@ -9799,8 +9627,7 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word); // DYNAMIC variables too!! - // Try not to add anything that would break netgames or timeattack replays here. - // You know, like consoleplayer, displayplayers, or gametime. + if (fastcmp(word,"gamemap")) { lua_pushinteger(L, gamemap); return 1; @@ -9881,24 +9708,23 @@ static inline int lib_getenum(lua_State *L) return 0; LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); return 1; + } else if (fastcmp(word,"consoleplayer")) { // Player controlling the console, basically our local player + if (consoleplayer < 0 || !playeringame[consoleplayer]) + return 0; + LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); + return 1; /*} else if (fastcmp(word,"admin")) { LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)"); if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer)) return 0; LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER); return 1;*/ - } else if (fastcmp(word,"emeralds")) { - lua_pushinteger(L, emeralds); - return 1; } else if (fastcmp(word,"gravity")) { lua_pushinteger(L, gravity); return 1; } else if (fastcmp(word,"VERSIONSTRING")) { lua_pushstring(L, VERSIONSTRING); return 1; - } else if (fastcmp(word, "token")) { - lua_pushinteger(L, token); - return 1; } else if (fastcmp(word,"gamespeed")) { lua_pushinteger(L, gamespeed); return 1; @@ -9932,6 +9758,12 @@ static inline int lib_getenum(lua_State *L) } 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; } return 0; } diff --git a/src/doomdef.h b/src/doomdef.h index 24b52e8d..ed41e346 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -138,8 +138,12 @@ #ifdef LOGMESSAGES extern FILE *logstream; +extern char logfilename[1024]; #endif +/* A mod name to further distinguish versions. */ +#define SRB2APPLICATION "SRB2Kart" + //#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 @@ -149,10 +153,10 @@ extern FILE *logstream; // most interface strings are ignored in development mode. // we use comprevision and compbranch instead. #else -#define VERSION 110 // Game version -#define SUBVERSION 0 // more precise version number -#define VERSIONSTRING "v1.1" -#define VERSIONSTRINGW L"v1.1" +#define VERSION 1 // Game version +#define SUBVERSION 2 // more precise version number +#define VERSIONSTRING "v1.2" +#define VERSIONSTRINGW L"v1.2" // 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! @@ -225,7 +229,7 @@ extern FILE *logstream; // 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 5 +#define MODVERSION 6 // Filter consvars by version // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. @@ -548,6 +552,9 @@ extern INT32 cv_debug; 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) + // if we ever make our alloc stuff... #define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL) @@ -633,11 +640,6 @@ 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? -#endif - #if !defined (_NDS) && !defined (_PSP) /// Allow the use of the SOC RESETINFO command. /// \note Builds that are tight on memory should disable this. @@ -674,6 +676,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// 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 +#define GL_SHADERS #endif // __DOOMDEF__ diff --git a/src/doomstat.h b/src/doomstat.h index 1f855da2..232a5af8 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -448,7 +448,7 @@ extern UINT8 maxXtraLife; // Max extra lives from rings extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations // For racing -extern UINT32 countdown, countdown2; +extern tic_t racecountdown, exitcountdown; extern fixed_t gravity; extern fixed_t mapobjectscale; @@ -549,7 +549,7 @@ extern consvar_t cv_downloading; // allow clients to downloading WADs. extern consvar_t cv_nettimeout; // SRB2Kart: Advanced server options menu extern consvar_t cv_jointimeout; extern consvar_t cv_maxping; -extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; +extern ticcmd_t netcmds[TICQUEUE][MAXPLAYERS]; extern INT32 serverplayer; extern INT32 adminplayers[MAXPLAYERS]; diff --git a/src/f_finale.c b/src/f_finale.c index 0d38d0e7..ade26bbe 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -449,6 +449,7 @@ static const char *credits[] = { "\"Lat\'\"", "\"Monster Iestyn\"", "\"Shuffle\"", + "\"SteelT\"", "", "\1Lead Artists", "Desmond \"Blade\" DesJardins", @@ -473,17 +474,17 @@ static const char *credits[] = { "\"DirkTheHusky\"", "\"LJSTAR\"", "\"MotorRoach\"", - "\"Mr. McScrewup\"", "\"Nev3r\"", + "\"rairai104n\"", "\"Ritz\"", "\"Rob\"", "\"SmithyGNC\"", "\"Snu\"", "\"Spherallic\"", + "\"TelosTurntable\"", "\"VAdaPEGA\"", "\"Virt\"", "\"Voltrix\"", - "\"zxyspku\"", "", "\1Sound Design", "James \"SeventhSentinel\" Hall", @@ -511,6 +512,7 @@ static const char *credits[] = { "Sherman \"CoatRack\" DesJardins", "Colette \"fickleheart\" Bordelon", "Vivian \"toaster\" Grannell", + "\"Gunla\"", "James \"SeventhSentinel\" Hall", "\"Lat\'\"", "\"MK\"", @@ -573,7 +575,7 @@ 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)+(86*15), "TYLER52", SKINCOLOR_NONE}, + {112, (15*100)+(17*38)+(88*15), "TYLER52", SKINCOLOR_NONE}, {0, 0, NULL, SKINCOLOR_NONE} }; diff --git a/src/f_wipe.c b/src/f_wipe.c index 6104504c..8bcb1278 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -373,7 +373,9 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) HWR_DoWipe(wipetype, wipeframe-1); // send in the wipe type and wipeframe because we need to cache the graphic else #endif - F_DoWipe(fmask); + if (rendermode != render_none) //this allows F_RunWipe to be called in dedicated servers + F_DoWipe(fmask); + I_OsPolling(); I_UpdateNoBlit(); diff --git a/src/g_game.c b/src/g_game.c index b8a1a3bf..bf0557d0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -43,7 +43,9 @@ #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 "b_bot.h" #include "m_cond.h" // condition sets #include "md5.h" // demo checksums @@ -233,7 +235,7 @@ mobj_t *hunt1; mobj_t *hunt2; mobj_t *hunt3; -UINT32 countdown, countdown2; // for racing +tic_t racecountdown, exitcountdown; // for racing fixed_t gravity; fixed_t mapobjectscale; @@ -287,7 +289,8 @@ UINT32 timesBeatenWithEmeralds; //@TODO put these all in a struct for namespacing purposes? static char demoname[128]; static UINT8 *demobuffer = NULL; -static UINT8 *demo_p, *demotime_p, *demoinfo_p; +static UINT8 *demotime_p, *demoinfo_p; +UINT8 *demo_p; static UINT8 *demoend; static UINT8 demoflags; static boolean demosynced = true; // console warning message @@ -782,7 +785,7 @@ void G_SetGameModified(boolean silent, boolean major) majormods = true; if (!silent) - CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to play record attack.\n")); + CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to play Record Attack.\n")); // If in record attack recording, cancel it. if (modeattacking) @@ -1884,7 +1887,7 @@ boolean G_Responder(event_t *ev) } } - if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demo.playback) + 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]) { @@ -1928,11 +1931,8 @@ boolean G_Responder(event_t *ev) return true; } - // Anything else opens the menu if not already open, except for a few keys... - if (!( - // Rankings - ev->data1 == gamecontrol[gc_scores][0] || ev->data1 == gamecontrol[gc_scores][1] - )) + // open menu but only w/ esc + if (ev->data1 == 32) { M_StartControlPanel(); @@ -2320,6 +2320,12 @@ void G_Ticker(boolean run) UINT32 i; INT32 buf; ticcmd_t *cmd; + UINT32 ra_timeskip = (modeattacking && !demo.playback && leveltime < starttime - TICRATE*4) ? 0 : (starttime - TICRATE*4 - 1); + // starttime - TICRATE*4 is where we want RA to start when we PLAY IT, so we will loop the main thinker on RA start to get it to this point, + // the reason this is done is to ensure that ghosts won't look out of synch with other map elements (objects, moving platforms...) + // when we REPLAY, don't skip, let the camera spin, do its thing etc~ + + // also the -1 is to ensure that the thinker runs in the loop below. P_MapStart(); // do player reborns if needed @@ -2358,7 +2364,7 @@ void G_Ticker(boolean run) default: I_Error("gameaction = %d\n", gameaction); } - buf = gametic % BACKUPTICS; + buf = gametic % TICQUEUE; if (!demo.playback) // read/write demo and check turbo cheat @@ -2392,12 +2398,16 @@ void G_Ticker(boolean run) switch (gamestate) { case GS_LEVEL: - if (demo.title) - F_TitleDemoTicker(); - P_Ticker(run); // tic the game - ST_Ticker(); - AM_Ticker(); - HU_Ticker(); + + for (; ra_timeskip < starttime - TICRATE*4; ra_timeskip++) // this looks weird but this is done to not break compability with older demos for now. + { + if (demo.title) + F_TitleDemoTicker(); + P_Ticker(run); // tic the game + ST_Ticker(); + AM_Ticker(); + HU_Ticker(); + } break; case GS_INTERMISSION: @@ -4583,7 +4593,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool { // Clear a bunch of variables tokenlist = token = sstimer = redscore = bluescore = lastmap = 0; - countdown = countdown2 = mapreset = 0; + racecountdown = exitcountdown = mapreset = 0; for (i = 0; i < MAXPLAYERS; i++) { @@ -4737,6 +4747,11 @@ char *G_BuildMapTitle(INT32 mapnum) #define DF_RECORDATTACK 0x02 // This demo is from record attack and contains its final completion time! #define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares! #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! @@ -4863,6 +4878,16 @@ 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); @@ -5901,6 +5926,8 @@ static rewindinfo_t *rewindhead = NULL; // Reverse chronological order void G_InitDemoRewind(void) { + CL_ClearRewinds(); + while (rewindhead) { rewindinfo_t *p = rewindhead->prev; @@ -6022,19 +6049,35 @@ void G_ConfirmRewind(tic_t rewindtime) CV_StealthSetValue(&cv_renderview, 0); - if (rewindtime > starttime) + if (rewindtime <= starttime) { - sound_disabled = true; // Prevent sound spam - demo.rewinding = true; + demo.rewinding = false; + G_DoPlayDemo(NULL); // Restart the current demo } else - demo.rewinding = false; + { + rewind_t *rewind; + sound_disabled = true; // Prevent sound spam + demo.rewinding = true; - G_DoPlayDemo(NULL); // Restart the current demo + 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++) { - //TryRunTics(1); G_Ticker((j % NEWTICRATERATIO) == 0); } @@ -6046,6 +6089,9 @@ void G_ConfirmRewind(tic_t rewindtime) COM_BufInsertText("renderview on\n"); + if (demo.freecam) + return; // don't touch from there + splitscreen = oldss; displayplayers[0] = olddp1; displayplayers[1] = olddp2; @@ -6321,6 +6367,10 @@ void G_BeginRecording(void) if (encoremode) demoflags |= DF_ENCORE; +#ifdef HAVE_BLUA + demoflags |= DF_LUAVARS; +#endif + // Setup header. M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12; WRITEUINT8(demo_p,VERSION); @@ -6417,11 +6467,17 @@ void G_BeginRecording(void) // 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 + LUA_ArchiveDemo(); +#endif + memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); memset(&ghostext,0,sizeof(ghostext)); @@ -6573,7 +6629,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) { 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 add-ons.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); + 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) { @@ -6585,7 +6641,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) 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 add-ons. Check the console for more information.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); + 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 { @@ -7416,7 +7472,7 @@ void G_DoPlayDemo(char *defdemoname) if (modeattacking) { - snprintf(msg, 1024, M_GetText("%s is a record attack replay with spectators, and is thus invalid.\n"), pdemoname); + 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); @@ -7430,7 +7486,7 @@ void G_DoPlayDemo(char *defdemoname) if (modeattacking && numslots > 1) { - snprintf(msg, 1024, M_GetText("%s is a record attack replay with multiple players, and is thus invalid.\n"), pdemoname); + 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); @@ -7479,6 +7535,18 @@ void G_DoPlayDemo(char *defdemoname) 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(); + + LUA_UnArchiveDemo(); + } +#endif + splitscreen = 0; if (demo.title) @@ -8091,8 +8159,18 @@ void G_StopDemo(void) 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) { diff --git a/src/g_game.h b/src/g_game.h index a69f9142..0edc13c7 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -31,6 +31,8 @@ extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; extern player_t players[MAXPLAYERS]; extern boolean playeringame[MAXPLAYERS]; +extern UINT8 *demo_p; + // ====================================== // DEMO playback/recording related stuff. // ====================================== @@ -60,6 +62,9 @@ struct demovars_s { DSM_WILLSAVE, DSM_SAVED } savemode; + + boolean freecam; + }; extern struct demovars_s demo; diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 9e454bcd..da802aaf 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -1,17 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief convert SRB2 map @@ -19,6 +14,7 @@ #include "../doomdef.h" #include "../doomstat.h" #ifdef HWRENDER +#include "hw_main.h" #include "hw_glob.h" #include "../r_local.h" #include "../z_zone.h" @@ -60,77 +56,12 @@ 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 *gr_polypool = NULL; -static UINT8 *gr_ppcurrent; -static size_t gr_ppfree; -#endif - -// only between levels, clear poly pool -static void HWR_ClearPolys(void) -{ -#ifndef ZPLANALLOC - gr_ppcurrent = gr_polypool; - gr_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); - gr_polypool = malloc(POLYPOOLSIZE); - if (!gr_polypool) - I_Error("HWR_InitPolyPool(): couldn't malloc polypool\n"); - HWR_ClearPolys(); -#endif -} - -void HWR_FreePolyPool(void) -{ -#ifndef ZPLANALLOC - if (gr_polypool) - free(gr_polypool); - gr_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 (!gr_polypool) - I_Error("Used gr_polypool without init!\n"); - if (!gr_ppcurrent) - I_Error("gr_ppcurrent == NULL!\n"); -#endif - - if (gr_ppfree < size) - I_Error("HWR_AllocPoly(): no more memory %u bytes left, %u bytes needed\n\n%s\n", - gr_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)"); - - p = (poly_t *)gr_ppcurrent; - gr_ppcurrent += size; - gr_ppfree -= size; -#endif p->numpts = numpts; return p; } @@ -139,17 +70,7 @@ 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 (gr_ppfree < size) - I_Error("HWR_AllocVertex(): no more memory %u bytes left, %u bytes needed\n\n%s\n", - gr_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)"); - - p = (polyvertex_t *)gr_ppcurrent; - gr_ppcurrent += size; - gr_ppfree -= size; -#endif return p; } @@ -157,16 +78,9 @@ 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 // @@ -577,8 +491,8 @@ static inline void SearchDivline(node_t *bsp, fdivline_t *divline) divline->dy = FIXED_TO_FLOAT(bsp->dy); } -#ifdef HWR_LOADING_SCREEN //Hurdler: implement a loading status +#ifdef HWR_LOADING_SCREEN static size_t ls_count = 0; static UINT8 ls_percent = 0; @@ -836,8 +750,6 @@ static INT32 SolveTProblem(void) return 0; CONS_Debug(DBG_RENDER, "Solving T-joins. This may take a while. Please wait...\n"); - CON_Drawer(); //let the user know what we are doing - I_FinishUpdate(); // page flip or blit buffer numsplitpoly = 0; @@ -964,11 +876,9 @@ void HWR_CreatePlanePolygons(INT32 bspnum) CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n"); #ifdef HWR_LOADING_SCREEN ls_count = ls_percent = 0; // reset the loading status -#endif CON_Drawer(); //let the user know what we are doing I_FinishUpdate(); // page flip or blit buffer - - HWR_ClearPolys(); +#endif // find min/max boundaries of map //CONS_Debug(DBG_RENDER, "Looking for boundaries of map...\n"); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index d49531bd..eb951149 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1,18 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief load and convert graphics to the hardware format @@ -20,6 +14,7 @@ #include "../doomdef.h" #ifdef HWRENDER +#include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" @@ -31,10 +26,6 @@ #include "../v_video.h" #include "../r_draw.h" -//Hurdler: 25/04/2000: used for new colormap code in hardware mode -//static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized) -boolean firetranslucent = false; - // Values set after a call to HWR_ResizeBlock() static INT32 blocksize, blockwidth, blockheight; @@ -139,17 +130,17 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, count--; texel = source[yfrac>>FRACBITS]; - - if (firetranslucent && (transtables[(texel<<8)+0x40000]!=texel)) - alpha = 0x80; - else - alpha = 0xff; + alpha = 0xff; //Hurdler: not perfect, but better than holes if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX && (mipmap->flags & TF_CHROMAKEYED)) - texel = HWR_CHROMAKEY_EQUIVALENTCOLORINDEX; + alpha = 0x00; + + //texel = HWR_CHROMAKEY_EQUIVALENTCOLORINDEX; + // Lat: Don't do that, some weirdos still use CYAN on their WALLTEXTURES for translucency :V + //Hurdler: 25/04/2000: now support colormap in hardware mode - else if (mipmap->colormap) + if (mipmap->colormap) texel = mipmap->colormap[texel]; // hope compiler will get this switch out of the loops (dreams...) @@ -181,16 +172,16 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, } -// resize the patch to be 3dfx compliant +// 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, - GrTexInfo *grInfo) + GLTexInfo *grInfo) { // Build the full textures from patches. - static const GrLOD_t gr_lods[9] = + static const GLlod_t gr_lods[9] = { GR_LOD_LOG2_256, GR_LOD_LOG2_128, @@ -205,7 +196,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, typedef struct { - GrAspectRatio_t aspect; + GLAspectRatio_t aspect; float max_s; float max_t; } booring_aspect_t; @@ -226,41 +217,21 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, INT32 j,k; INT32 max,min; - // find a power of 2 width/height - if (cv_grrounddown.value) - { - blockwidth = 256; - while (originalwidth < blockwidth) - blockwidth >>= 1; - if (blockwidth < 1) - I_Error("3D GenerateTexture : too small"); + // 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; - blockheight = 256; - while (originalheight < blockheight) - blockheight >>= 1; - if (blockheight < 1) - I_Error("3D GenerateTexture : too small"); - } - else - { - //size up to nearest power of 2 - blockwidth = 1; - while (blockwidth < originalwidth) - blockwidth <<= 1; - // scale down the original graphics to fit in 256 - if (blockwidth > 2048) - blockwidth = 2048; - //I_Error("3D GenerateTexture : too big"); - - //size up to nearest power of 2 - blockheight = 1; - while (blockheight < originalheight) - blockheight <<= 1; - // scale down the original graphics to fit in 256 - if (blockheight > 2048) - blockheight = 2048; - //I_Error("3D GenerateTexture : too big"); - } + // 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) @@ -324,7 +295,7 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap) { UINT8 *block; INT32 bpp, i; - UINT16 bu16 = ((0x00 <<8) | HWR_CHROMAKEY_EQUIVALENTCOLORINDEX); + UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX); bpp = format2bpp[grMipmap->grInfo.format]; block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data)); @@ -335,8 +306,8 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap) case 2: // fill background with chromakey, alpha = 0 for (i = 0; i < blocksize; i++) - //[segabor] memcpy(block+i*sizeof(UINT16), &bu16, sizeof(UINT16)); + break; case 4: memset(block, 0x00, blocksize*sizeof(UINT32)); break; } @@ -379,6 +350,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) grtex->mipmap.height = (UINT16)blockheight; grtex->mipmap.grInfo.format = textureformat; + grtex->mipmap.colormap = colormaps; + +#ifdef GLENCORE + if (encoremap) + grtex->mipmap.colormap += (256*32); +#endif + block = MakeBlock(&grtex->mipmap); if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading) @@ -430,7 +408,7 @@ 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 (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) +void HWR_MakePatch (patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) { INT32 newwidth, newheight; @@ -445,8 +423,8 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm grPatch->leftoffset = SHORT(patch->leftoffset); grPatch->topoffset = SHORT(patch->topoffset); - // find the good 3dfx size (boring spec) - HWR_ResizeBlock (SHORT(patch->width), SHORT(patch->height), &grMipmap->grInfo); + // resize patch + HWR_ResizeBlock(SHORT(patch->width), SHORT(patch->height), &grMipmap->grInfo); grMipmap->width = (UINT16)blockwidth; grMipmap->height = (UINT16)blockheight; @@ -465,23 +443,12 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm Z_Free(grMipmap->grInfo.data); grMipmap->grInfo.data = NULL; - // if rounddown, rounddown patches as well as textures - if (cv_grrounddown.value) - { - newwidth = blockwidth; - newheight = blockheight; - } - else - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(grPatch->width, blockwidth); - newheight = min(grPatch->height, blockheight); - } + newwidth = min(grPatch->width, blockwidth); + newheight = min(grPatch->height, blockheight); if (makebitmap) { MakeBlock(grMipmap); - HWR_DrawPatchInCache(grMipmap, newwidth, newheight, blockwidth*format2bpp[grMipmap->grInfo.format], @@ -495,7 +462,6 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm grPatch->max_t = (float)newheight / (float)blockheight; } - // ================================================= // CACHING HANDLING // ================================================= @@ -515,10 +481,10 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch) { GLPatch_t* const grpatch = patch; (void)patchnum; //unused - while (grpatch->mipmap.nextcolormap) + while (grpatch->mipmap->nextcolormap) { - GLMipmap_t *grmip = grpatch->mipmap.nextcolormap; - grpatch->mipmap.nextcolormap = grmip->nextcolormap; + GLMipmap_t *grmip = grpatch->mipmap->nextcolormap; + grpatch->mipmap->nextcolormap = grmip->nextcolormap; if (grmip->grInfo.data) Z_Free(grmip->grInfo.data); free(grmip); } @@ -562,7 +528,7 @@ void HWR_PrepLevelCache(size_t pnumtextures) gr_numtextures = pnumtextures; gr_textures = calloc(pnumtextures, sizeof (*gr_textures)); if (gr_textures == NULL) - I_Error("3D can't alloc gr_textures"); + I_Error("HWR_PrepLevelCache: can't alloc gr_textures"); } void HWR_SetPalette(RGBA_t *palette) @@ -593,7 +559,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex) GLTexture_t *grtex; #ifdef PARANOIA if ((unsigned)tex >= gr_numtextures) - I_Error(" HWR_GetTexture: tex >= numtextures\n"); + I_Error("HWR_GetTexture: tex >= numtextures\n"); #endif grtex = &gr_textures[tex]; @@ -611,8 +577,13 @@ GLTexture_t *HWR_GetTexture(INT32 tex) static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { +#ifdef GLENCORE + UINT8 *flat; + size_t steppy; +#endif size_t size, pflatsize; + // setup the texture info grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; @@ -652,15 +623,37 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) // the flat raw data needn't be converted with palettized textures W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), PU_HWRCACHE, &grMipmap->grInfo.data)); + +#ifdef GLENCORE + flat = grMipmap->grInfo.data; + for (steppy = 0; steppy < size; steppy++) + if (flat[steppy] != HWR_PATCHES_CHROMAKEY_COLORINDEX) + flat[steppy] = grMipmap->colormap[flat[steppy]]; +#endif } // Download a Doom 'flat' to the hardware cache and make it ready for use -void HWR_GetFlat(lumpnum_t flatlumpnum) +void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap) { GLMipmap_t *grmip; - grmip = &HWR_GetCachedGLPatch(flatlumpnum)->mipmap; + grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; + + grmip->colormap = colormaps; + +#ifdef GLENCORE + if (!noencoremap && encoremap) + grmip->colormap += (256*32); +#endif + + grmip->colormap = colormaps; + +#ifdef GLENCORE + if (!noencoremap && encoremap) + grmip->colormap += (256*32); +#endif + if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFlat(grmip, flatlumpnum); @@ -697,22 +690,22 @@ 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->grInfo.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 *ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - HWR_MakePatch(ptr, gpatch, &gpatch->mipmap, true); + patch_t *patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + HWR_MakePatch(patch, 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(ptr); + Z_Free(patch); } - HWD.pfnSetTexture(&gpatch->mipmap); + HWD.pfnSetTexture(gpatch->mipmap); // The system-memory patch data can be purged now. - Z_ChangeTag(gpatch->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); } @@ -732,7 +725,7 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) // search for the mimmap // skip the first (no colormap translated) - for (grmip = &gpatch->mipmap; grmip->nextcolormap; ) + for (grmip = gpatch->mipmap; grmip->nextcolormap; ) { grmip = grmip->nextcolormap; if (grmip->colormap == colormap) @@ -762,164 +755,10 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch) if (!gpatch) return; - Z_ChangeTag(gpatch->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(gpatch, PU_HWRPATCHINFO_UNLOCKED); } -static const INT32 picmode2GR[] = -{ - GR_TEXFMT_P_8, // PALETTE - 0, // INTENSITY (unsupported yet) - GR_TEXFMT_ALPHA_INTENSITY_88, // INTENSITY_ALPHA (corona use this) - 0, // RGB24 (unsupported yet) - GR_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; - - grpatch = HWR_GetCachedGLPatch(lumpnum); - - if (!grpatch->mipmap.downloaded && !grpatch->mipmap.grInfo.data) - { - pic_t *pic; - UINT8 *block; - size_t len; - INT32 newwidth, newheight; - - 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; - - // find the good 3dfx size (boring spec) - HWR_ResizeBlock (grpatch->width, grpatch->height, &grpatch->mipmap.grInfo); - grpatch->mipmap.width = (UINT16)blockwidth; - grpatch->mipmap.height = (UINT16)blockheight; - - if (pic->mode == PALETTE) - grpatch->mipmap.grInfo.format = textureformat; // can be set by driver - else - grpatch->mipmap.grInfo.format = picmode2GR[pic->mode]; - - Z_Free(grpatch->mipmap.grInfo.data); - - // allocate block - block = MakeBlock(&grpatch->mipmap); - - // if rounddown, rounddown patches as well as textures - if (cv_grrounddown.value) - { - newwidth = blockwidth; - newheight = blockheight; - } - else - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(SHORT(pic->width),blockwidth); - newheight = min(SHORT(pic->height),blockheight); - } - - - if (grpatch->width == blockwidth && - grpatch->height == blockheight && - format2bpp[grpatch->mipmap.grInfo.format] == format2bpp[picmode2GR[pic->mode]]) - { - // no conversion needed - M_Memcpy(grpatch->mipmap.grInfo.data, pic->data,len); - } - else - HWR_DrawPicInCache(block, newwidth, newheight, - blockwidth*format2bpp[grpatch->mipmap.grInfo.format], - pic, - format2bpp[grpatch->mipmap.grInfo.format]); - - Z_Unlock(pic); - Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); - - grpatch->mipmap.flags = 0; - grpatch->max_s = (float)newwidth / (float)blockwidth; - grpatch->max_t = (float)newheight / (float)blockheight; - } - HWD.pfnSetTexture(&grpatch->mipmap); - //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded); - - return grpatch; -} - GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) { aatree_t *hwrcache = wadfiles[wadnum]->hwrcache; @@ -930,6 +769,7 @@ GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); grpatch->wadnum = wadnum; grpatch->lumpnum = lumpnum; + grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); M_AATreeSet(hwrcache, lumpnum, grpatch); } @@ -1033,7 +873,7 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { GLMipmap_t *grmip; - grmip = &HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; + grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFadeMask(grmip, fademasklumpnum); diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index a6352708..8ef5636a 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -70,16 +70,17 @@ #include #include "../v_video.h" +#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" +#include "../r_main.h" // for cv_fov #ifdef HAVE_SPHEREFRUSTRUM -static GLfloat viewMatrix[16]; -static GLfloat projMatrix[16]; +static GLdouble viewMatrix[16]; +static GLdouble projMatrix[16]; float frustum[6][4]; #endif @@ -320,12 +321,12 @@ void gld_clipper_Clear(void) #define RMUL (1.6f/1.333333f) -angle_t gld_FrustumAngle(void) +angle_t gld_FrustumAngle(angle_t tiltangle) { double floatangle; angle_t a1; - float tilt = (float)fabs(((double)(int)aimingangle) / ANG1); + float tilt = (float)fabs(((double)(int)tiltangle) / ANG1); // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function @@ -334,12 +335,10 @@ angle_t gld_FrustumAngle(void) float render_multiplier = 64.0f / render_fovratio / RMUL; if (tilt > 90.0f) - { tilt = 90.0f; - } // If the pitch is larger than this you can look all around at a FOV of 90 - if (abs((signed)aimingangle) > 46 * ANG1) + if (abs((signed)tiltangle) > 46 * ANG1) return 0xffffffff; // ok, this is a gross hack that barely works... @@ -352,7 +351,7 @@ angle_t gld_FrustumAngle(void) } // SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either -// compiler complains about (p)glGetDoublev anyway, in case anyone wants this +// compiler complains about (p)glGetFloatv anyway, in case anyone wants this // only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks // btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h #ifdef HAVE_SPHEREFRUSTRUM @@ -381,7 +380,7 @@ void gld_FrustrumSetup(void) float t; float clip[16]; - pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix); clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12); @@ -463,4 +462,4 @@ boolean gld_SphereInFrustum(float x, float y, float z, float radius) } return true; } -#endif +#endif \ No newline at end of file diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h index 3ba26e5e..27a2ed1e 100644 --- a/src/hardware/hw_clip.h +++ b/src/hardware/hw_clip.h @@ -17,7 +17,7 @@ boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle); void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle); void gld_clipper_Clear(void); -angle_t gld_FrustumAngle(void); +angle_t gld_FrustumAngle(angle_t tiltangle); #ifdef HAVE_SPHEREFRUSTRUM void gld_FrustrumSetup(void); boolean gld_SphereInFrustum(float x, float y, float z, float radius); diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index 4bbc578e..a96d4c91 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -1,77 +1,101 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 -/// \brief defines structures and exports for the standard 3D driver DLL used by Doom Legacy +/// \brief defines structures and exports for the standard GPU driver #ifndef _HWR_DATA_ #define _HWR_DATA_ -#if defined (_WIN32) && !defined (__CYGWIN__) && !defined (_XBOX) -//#define WIN32_LEAN_AND_MEAN -#define RPC_NO_WINDOWS_H -#include -#endif - #include "../doomdef.h" -//THIS MUST DISAPPEAR!!! -#include "hw_glide.h" #include "../screen.h" - // ========================================================================== // 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 +{ + GLlod_t smallLodLog2; + GLlod_t largeLodLog2; + GLAspectRatio_t aspectRatioLog2; + GLTextureFormat_t format; + void *data; +} GLTexInfo; + // grInfo.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 { - GrTexInfo grInfo; //for TexDownloadMipMap - FxU32 flags; - UINT16 height; - UINT16 width; - UINT32 downloaded; // the dll driver have it in there cache ? + GLTexInfo grInfo; + unsigned long flags; + UINT16 width, height; + UINT32 downloaded; // tex_downloaded - struct GLMipmap_s *nextcolormap; - const UINT8 *colormap; - - // opengl - struct GLMipmap_s *nextmipmap; // opengl : liste of all texture in opengl driver + struct GLMipmap_s *nextmipmap; + struct GLMipmap_s *nextcolormap; + const UINT8 *colormap; }; typedef struct GLMipmap_s GLMipmap_t; - // // Doom texture info, as cached for hardware rendering // struct GLTexture_s { - GLMipmap_t mipmap; - float scaleX; //used for scaling textures on walls - float scaleY; + GLMipmap_t mipmap; + float scaleX; //used for scaling textures on walls + float scaleY; }; typedef struct GLTexture_s GLTexture_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 // This is returned by W_CachePatchNum()/W_CachePatchName(), when rendermode // is 'render_opengl'. Else it returns the normal patch_t data. - struct GLPatch_s { // the 4 first fields come right away from the original patch_t @@ -83,8 +107,10 @@ 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; -}; + GLMipmap_t *mipmap; + + boolean notfound; // if the texture file was not found, mark it here (used in model texture loading) +} ATTRPACK; typedef struct GLPatch_s GLPatch_t; #endif //_HWR_DATA_ diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index b37850bb..af545191 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -19,6 +19,7 @@ #ifndef _HWR_DEFS_ #define _HWR_DEFS_ #include "../doomtype.h" +#include "../r_defs.h" #define ZCLIP_PLANE 4.0f // Used for the actual game drawing #define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures @@ -41,17 +42,8 @@ typedef unsigned char FBOOLEAN; // ========================================================================== // byte value for paletted graphics, which represent the transparent color -#ifdef _NDS -// NDS is hardwired to use zero as transparent color -#define HWR_PATCHES_CHROMAKEY_COLORINDEX 0 -#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 1 -#else #define HWR_PATCHES_CHROMAKEY_COLORINDEX 247 #define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 220 -#endif - -// 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 @@ -73,8 +65,6 @@ struct FColorARGB typedef struct FColorARGB ARGB_t; typedef struct FColorARGB FColorARGB; - - // ========================================================================== // VECTORS // ========================================================================== @@ -85,22 +75,65 @@ typedef struct FLOAT x,y; } F2DCoord, v2d_t; -// Simple 3D vector -typedef struct FVector -{ - FLOAT x,y,z; -} FVector; +// ====================== +// wallVert3D +// ---------------------- +// :crab: IS GONE! :crab: +// ====================== -// 3D model vector (coords + texture coords) +// ----------- +// structures +// ----------- + +// a vertex of a Doom 'plane' polygon typedef struct { - //FVector Point; - FLOAT x,y,z; - FLOAT s,t,w; // texture coordinates -} v3d_t, wallVert3D; + float x; + float y; + float z; +} polyvertex_t; -//Hurdler: Transform (coords + angles) -//BP: transform order : scale(rotation_x(rotation_y(translation(v)))) +#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 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; // Kart features #define USE_FTRANSFORM_ANGLEZ @@ -124,18 +157,17 @@ typedef struct #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; - FUINT argb; // flat-shaded color - FLOAT sow; // s texture ordinate (s over w) - FLOAT tow; // t texture ordinate (t over w) + FLOAT s,t; } FOutVector; - // ========================================================================== // RENDER MODES // ========================================================================== @@ -144,7 +176,7 @@ typedef struct // You pass a combination of these flags to DrawPolygon() enum EPolyFlags { - // the first 5 are mutually exclusive + // the first 5 are mutually exclusive PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture) PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency @@ -156,7 +188,7 @@ enum EPolyFlags PF_Fog = 0x00000040, // Fog blocks PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest, - // other flag bits + // other flag bits PF_Occlude = 0x00000100, // Update the depth buffer PF_NoDepthTest = 0x00000200, // Disable the depth test mode @@ -164,21 +196,15 @@ enum EPolyFlags 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, // Use the small white texture - PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona - PF_Unused = 0x00008000, // Unused + PF_NoTexture = 0x00002000, // Disable texture + PF_Ripple = 0x00004000, // Water shader effect + // 0x00008000 PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapY = 0x00040000, // Force repeat texture on Y - 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, + // 0x20000000 + // 0x40000000 + // 0x80000000 }; @@ -191,46 +217,42 @@ enum ETextureFlags TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 }; -#ifdef TODO -struct FTextureInfo -{ - FUINT Width; // Pixels - FUINT Height; // Pixels - FUBYTE *TextureData; // Image data - FUINT Format; // FORMAT_RGB, ALPHA ... - FBITFIELD Flags; // Flags to tell driver about texture (see ETextureFlags) - void DriverExtra; // (OpenGL texture object nr, ...) - // chromakey enabled,... - - struct FTextureInfo *Next; // Manage list of downloaded textures. -}; -#else typedef struct GLMipmap_s FTextureInfo; -#endif + +// jimita 14032019 +struct FLightInfo +{ + FUINT light_level; + FUINT fade_start; + FUINT fade_end; +}; +typedef struct FLightInfo FLightInfo; // Description of a renderable surface struct FSurfaceInfo { - FUINT PolyFlags; // Surface flags -- UNUSED YET -- - RGBA_t FlatColor; // Flat-shaded color used with PF_Modulated mode + FUINT PolyFlags; + RGBA_t PolyColor; + RGBA_t TintColor; + RGBA_t FadeColor; + FLightInfo LightInfo; // jimita 14032019 }; typedef struct FSurfaceInfo FSurfaceInfo; -//Hurdler: added for backward compatibility enum hwdsetspecialstate { - HWD_SET_FOG_TABLE = 1, - HWD_SET_FOG_MODE, - HWD_SET_FOG_COLOR, - HWD_SET_FOG_DENSITY, - HWD_SET_FOV, + HWD_SET_SHADERS, + HWD_SET_TEXTUREFILTERMODE, HWD_SET_TEXTUREANISOTROPICMODE, + HWD_NUMSTATE }; - typedef enum hwdsetspecialstate hwdspecialstate_t; +#define GL_DEFAULTMIX 0x00000000 +#define GL_DEFAULTFOG 0xFF000000 + enum hwdfiltermode { HWD_SET_TEXTUREFILTER_POINTSAMPLED, @@ -241,5 +263,4 @@ enum hwdfiltermode HWD_SET_TEXTUREFILTER_MIXED3, }; - #endif //_HWR_DEFS_ diff --git a/src/hardware/hw_dll.h b/src/hardware/hw_dll.h index 46645278..14040432 100644 --- a/src/hardware/hw_dll.h +++ b/src/hardware/hw_dll.h @@ -54,8 +54,6 @@ #endif #endif -typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR; - // ========================================================================== // MATHS // ========================================================================== @@ -63,7 +61,8 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR; // Constants #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360 -void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/; +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 b39103ee..ba069420 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,17 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief miscellaneous drawing (mainly 2d) @@ -23,6 +18,7 @@ #include "../doomdef.h" #ifdef HWRENDER +#include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" @@ -41,9 +37,6 @@ #define O_BINARY 0 #endif -float gr_patch_scalex; -float gr_patch_scaley; - #if defined(_MSC_VER) #pragma pack(1) #endif @@ -63,9 +56,6 @@ typedef struct #if defined(_MSC_VER) #pragma pack() #endif -typedef UINT8 GLRGB[3]; - -#define BLENDMODE PF_Translucent static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; @@ -119,12 +109,12 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = gpatch->max_s; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -220,7 +210,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // if it's meant to cover the whole screen, black out the rest // 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) + 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); @@ -228,7 +218,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, const UINT8 *source = (const UINT8 *)(column) + 3; HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); Z_Free(realpatch); - }*/ + } // centre screen if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) { @@ -279,19 +269,19 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (option & V_FLIP) { - v[0].sow = v[3].sow = gpatch->max_s; - v[2].sow = v[1].sow = 0.0f; + v[0].s = v[3].s = gpatch->max_s; + v[2].s = v[1].s = 0.0f; } else { - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = gpatch->max_s; } - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -302,11 +292,11 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (alphalevel) { FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[hudtrans]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[hudtrans]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[hudtrans]; - else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; + 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]; + else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -368,7 +358,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // if it's meant to cover the whole screen, black out the rest // 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) + 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); @@ -376,7 +366,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal const UINT8 *source = (const UINT8 *)(column) + 3; HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); Z_Free(realpatch); - }*/ + } // centre screen if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) { @@ -440,12 +430,12 @@ 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].sow = v[3].sow = ((sx)/(float)SHORT(gpatch->width) )*gpatch->max_s; - v[2].sow = v[1].sow = ((w )/(float)SHORT(gpatch->width) )*gpatch->max_s; - v[0].tow = v[1].tow = ((sy)/(float)SHORT(gpatch->height))*gpatch->max_t; - v[2].tow = v[3].tow = ((h )/(float)SHORT(gpatch->height))*gpatch->max_t; + 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; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -456,11 +446,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal if (alphalevel) { FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[hudtrans]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[hudtrans]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[hudtrans]; - else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; + 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]; + else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -468,41 +458,6 @@ 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].sow = v[3].sow = 0; - v[2].sow = v[1].sow = patch->max_s; - v[0].tow = v[1].tow = 0; - v[2].tow = v[3].tow = 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, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); -} - // ========================================================================== // V_VIDEO.C STUFF // ========================================================================== @@ -563,12 +518,12 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; // flat is 64x64 lod and texture offsets are [0.0, 1.0] - v[0].sow = v[3].sow = (float)((x & flatflag)/dflatsize); - v[2].sow = v[1].sow = (float)(v[0].sow + w/dflatsize); - v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize); - v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize); + v[0].s = v[3].s = (float)((x & flatflag)/dflatsize); + v[2].s = v[1].s = (float)(v[0].s + w/dflatsize); + 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); + HWR_GetFlat(flatlumpnum, false); // Never Encore map drawflatfill, duh. //Hurdler: Boris, the same comment as above... but maybe for pics // it not a problem since they don't have any transparent pixel @@ -598,20 +553,20 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) v[2].y = v[3].y = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 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.FlatColor.rgba = UINT2RGBA(0x01010160); - Surf.FlatColor.s.alpha = (strength*8); + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); } else // Do TRANSMAP** fade. { - Surf.FlatColor.rgba = pLocalPalette[color].rgba; - Surf.FlatColor.s.alpha = (UINT8)(strength*25.5f); + 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); } @@ -632,13 +587,13 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) v[2].y = v[3].y = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 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; - Surf.FlatColor.rgba = UINT2RGBA(color); - Surf.FlatColor.s.alpha = 0x80; + Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.s.alpha = 0x80; HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -773,6 +728,7 @@ void HWR_DrawViewBorder(INT32 clearlines) } + // ========================================================================== // AM_MAP.C DRAWING STUFF // ========================================================================== @@ -797,225 +753,6 @@ void HWR_drawAMline(const fline_t *fl, INT32 color) HWD.pfnDraw2DLine(&v1, &v2, color_rgba); } -// -----------------+ -// HWR_DrawFill : draw flat coloured rectangle, with no texture -// -----------------+ -void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) -{ - FOutVector v[4]; - FSurfaceInfo Surf; - float fx, fy, fw, fh; - - if (w < 0 || h < 0) - return; // consistency w/ software - -// 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; - - 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; - fh *= dupy; - - if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) - { - if (color & V_SNAPTORIGHT) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); - else if (!(color & V_SNAPTOLEFT)) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; - } - if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) - { - // same thing here - if (color & V_SNAPTOBOTTOM) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); - else if (!(color & V_SNAPTOTOP)) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; - } - if (color & V_SPLITSCREEN) - fy += ((float)BASEVIDHEIGHT * dupy)/2; - if (color & V_HORZSCREEN) - fx += ((float)BASEVIDWIDTH * dupx)/2; - } - - 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; - - //Hurdler: do we still use this argb color? if not, we should remove it - v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; - - Surf.FlatColor = V_GetColor(color); - - HWD.pfnDrawPolygon(&Surf, v, 4, - PF_Modulated|PF_NoTexture|PF_NoDepthTest); -} - - -// -------------------+ -// 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) -{ - FOutVector v[4]; - FSurfaceInfo Surf; - float fx, fy, fw, fh; - - if (w < 0 || h < 0) - return; // consistency w/ software - -// 3--2 -// | /| -// |/ | -// 0--1 - - fx = (float)x; - fy = (float)y; - fw = (float)w; - fh = (float)h; - - if (!(options & V_NOSCALESTART)) - { - float dupx = (float)vid.dupx, dupy = (float)vid.dupy; - - 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; - fh *= dupy; - - if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f) - { - if (options & V_SNAPTORIGHT) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); - else if (!(options & V_SNAPTOLEFT)) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; - } - if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f) - { - // same thing here - if (options & V_SNAPTOBOTTOM) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); - else if (!(options & V_SNAPTOTOP)) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; - } - if (options & V_SPLITSCREEN) - fy += ((float)BASEVIDHEIGHT * dupy)/2; - if (options & V_HORZSCREEN) - fx += ((float)BASEVIDWIDTH * dupx)/2; - } - - 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; - - //Hurdler: do we still use this argb color? if not, we should remove it - v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; - - Surf.FlatColor.rgba = UINT2RGBA(color); - Surf.FlatColor.s.alpha = 0x80; - - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); -} - // -----------------+ // HWR_DrawDiag : draw flat coloured rectangle, with no texture // -----------------+ @@ -1097,22 +834,234 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color) v[3].y = fy - fh; v[2].y = fy - fwait; - //Hurdler: do we still use this argb color? if not, we should remove it - v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 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; - Surf.FlatColor = V_GetColor(color); + Surf.PolyColor = V_GetColor(color); HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_NoTexture|PF_NoDepthTest); } +// -------------------+ +// 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) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + float fx, fy, fw, fh; + if (w < 0 || h < 0) + return; // consistency w/ software + +// 3--2 +// | /| +// |/ | +// 0--1 + + fx = (float)x; + fy = (float)y; + fw = (float)w; + fh = (float)h; + + if (!(options & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + 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; + fh *= dupy; + + if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f) + { + if (options & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(options & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + } + if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f) + { + // same thing here + if (options & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(options & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + } + if (options & V_SPLITSCREEN) + fy += ((float)BASEVIDHEIGHT * dupy)/2; + if (options & V_HORZSCREEN) + fx += ((float)BASEVIDWIDTH * dupx)/2; + + } + + 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; + + Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.s.alpha = 0x80; + + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); +} + +// -----------------+ +// HWR_DrawFill : draw flat coloured rectangle, with no texture +// -----------------+ +void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + float fx, fy, fw, fh; + + if (w < 0 || h < 0) + return; // consistency w/ software + +// 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; + + 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; + fh *= dupy; + + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) + { + if (color & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(color & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + } + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) + { + // same thing here + if (color & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(color & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + } + if (color & V_SPLITSCREEN) + fy += ((float)BASEVIDHEIGHT * dupy)/2; + if (color & V_HORZSCREEN) + fx += ((float)BASEVIDWIDTH * dupx)/2; + + } + + 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; + + Surf.PolyColor = V_GetColor(color); + + HWD.pfnDrawPolygon(&Surf, v, 4, + PF_Modulated|PF_NoTexture|PF_NoDepthTest); +} #ifdef HAVE_PNG @@ -1196,21 +1145,24 @@ UINT8 *HWR_GetScreenshot(void) return buf; } -boolean HWR_Screenshot(const char *lbmname) +boolean HWR_Screenshot(const char *pathname) { boolean ret; UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); if (!buf) + { + CONS_Debug(DBG_RENDER, "HWR_Screenshot: Failed to allocate memory\n"); return false; + } // returns 24bit 888 RGB HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); #ifdef USE_PNG - ret = M_SavePNG(lbmname, buf, vid.width, vid.height, NULL); + ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL); #else - ret = saveTGA(lbmname, buf, vid.width, vid.height); + ret = saveTGA(pathname, buf, vid.width, vid.height); #endif free(buf); return ret; diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 54bd9e78..bf8eb40f 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,21 +1,15 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 -/// \brief imports/exports for the 3D hardware low-level interface API +/// \brief imports/exports for the GPU hardware low-level interface API #ifndef __HWR_DRV_H__ #define __HWR_DRV_H__ @@ -32,13 +26,7 @@ // STANDARD DLL EXPORTS // ========================================================================== -EXPORT boolean HWRAPI(Init) (I_Error_t ErrorFunction); -#ifndef HAVE_SDL -EXPORT void HWRAPI(Shutdown) (void); -#endif -#ifdef _WINDOWS -EXPORT void HWRAPI(GetModeList) (vmode_t **pvidmodes, INT32 *numvidmodes); -#endif +EXPORT boolean HWRAPI(Init) (void); #if defined (PURESDL) || defined (macintosh) EXPORT void HWRAPI(SetPalette) (INT32 *, RGBA_t *gamma); #else @@ -58,14 +46,13 @@ 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, UINT8 *color); +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(CreateModelVBOs) (model_t *model); -EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); +EXPORT void HWRAPI(SetTransform) (FTransform *stransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); -EXPORT INT32 HWRAPI(GetRenderVersion) (void); -#define SCREENVERTS 10 -EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); +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); @@ -74,6 +61,22 @@ EXPORT void HWRAPI(DrawIntermissionBG) (void); EXPORT void HWRAPI(MakeScreenTexture) (void); EXPORT void HWRAPI(MakeScreenFinalTexture) (void); EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); + +#define SCREENVERTS 10 +EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); + +// jimita +EXPORT boolean HWRAPI(LoadShaders) (void); +EXPORT void HWRAPI(KillShaders) (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); + // ========================================================================== // HWR DRIVER OBJECT, FOR CLIENT PROGRAM // ========================================================================== @@ -93,18 +96,11 @@ struct hwdriver_s ReadRect pfnReadRect; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; - SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility + SetSpecialState pfnSetSpecialState; DrawModel pfnDrawModel; CreateModelVBOs pfnCreateModelVBOs; SetTransform pfnSetTransform; GetTextureUsed pfnGetTextureUsed; - GetRenderVersion pfnGetRenderVersion; -#ifdef _WINDOWS - GetModeList pfnGetModeList; -#endif -#ifndef HAVE_SDL - Shutdown pfnShutdown; -#endif PostImgRedraw pfnPostImgRedraw; FlushScreenTextures pfnFlushScreenTextures; StartScreenWipe pfnStartScreenWipe; @@ -114,16 +110,25 @@ struct hwdriver_s MakeScreenTexture pfnMakeScreenTexture; MakeScreenFinalTexture pfnMakeScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture; + + RenderSkyDome pfnRenderSkyDome; + + LoadShaders pfnLoadShaders; + KillShaders pfnKillShaders; + SetShader pfnSetShader; + UnSetShader pfnUnSetShader; + + LoadCustomShader pfnLoadCustomShader; + InitCustomShaders pfnInitCustomShaders; + + StartBatching pfnStartBatching; + RenderBatches pfnRenderBatches; }; extern struct hwdriver_s hwdriver; -//Hurdler: 16/10/99: added for OpenGL gamma correction -//extern RGBA_t gamma_correction; - #define HWD hwdriver #endif //not defined _CREATE_DLL_ -#endif //__HWR_DRV_H__ - +#endif //__HWR_DRV_H__ \ No newline at end of file diff --git a/src/hardware/hw_glide.h b/src/hardware/hw_glide.h deleted file mode 100644 index 2625d586..00000000 --- a/src/hardware/hw_glide.h +++ /dev/null @@ -1,71 +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 Declaration needed by Glide renderer -/// !!! To be replaced by our own def in the future !!! - -#ifndef _GLIDE_H_ -#define _GLIDE_H_ - -#ifndef __GLIDE_H__ - -typedef unsigned long FxU32; -typedef long FxI32; - -typedef FxI32 GrAspectRatio_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 FxI32 GrLOD_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 FxI32 GrTextureFormat_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 -{ - GrLOD_t smallLodLog2; - GrLOD_t largeLodLog2; - GrAspectRatio_t aspectRatioLog2; - GrTextureFormat_t format; - void *data; -} GrTexInfo; - -#endif // __GLIDE_H__ (defined in ) - -#endif // _GLIDE_H_ diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 9656e54e..3d03e7fa 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,18 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief globals (shared data & code) for hw_ modules @@ -21,78 +15,18 @@ #define _HWR_GLOB_H_ #include "hw_defs.h" -#include "hw_main.h" #include "../m_misc.h" - -// the original aspect ratio of Doom graphics isn't square -#define ORIGINAL_ASPECT (320.0f/200.0f) +#include "../r_defs.h" // Uncomment this to enable the OpenGL loading screen //#define HWR_LOADING_SCREEN -// ----------- -// 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 gr_vissprite_s -{ - // Doubly linked list - struct gr_vissprite_s *prev; - struct gr_vissprite_s *next; - float x1, x2; - 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 - float z1, z2; -} gr_vissprite_t; - // -------- // hw_bsp.c // -------- extern extrasubsector_t *extrasubsectors; extern size_t addsubsector; -void HWR_InitPolyPool(void); -void HWR_FreePolyPool(void); - // -------- // hw_cache.c // -------- @@ -100,12 +34,14 @@ void HWR_InitTextureCache(void); void HWR_FreeTextureCache(void); void HWR_FreeExtraSubsectors(void); -void HWR_GetFlat(lumpnum_t flatlumpnum); +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_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); @@ -114,13 +50,9 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- -extern float gr_patch_scalex; -extern float gr_patch_scaley; - extern consvar_t cv_grrounddown; // on/off extern INT32 patchformat; extern INT32 textureformat; -extern boolean firetranslucent; -#endif //_HW_GLOB_ +#endif //_HW_GLOB_ \ No newline at end of file diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index ee0cca74..079349c3 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,21 +1,14 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 -/// \brief Corona/Dynamic/Static lighting add on by Hurdler -/// !!! Under construction !!! #include "../doomdef.h" @@ -31,1346 +24,4 @@ #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[4]; // 4 players for splitscreen modes -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 - // UNDEFINED: 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 Graue 03-10-2004 - &lspr[NOLIGHT], // SPR_RBUZ Graue 03-10-2004 - &lspr[NOLIGHT], // SPR_JETB - &lspr[NOLIGHT], // SPR_JETW - &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_JJAW - &lspr[NOLIGHT], // SPR_SNLR - &lspr[NOLIGHT], // SPR_VLTR - &lspr[NOLIGHT], // SPR_PNTY - &lspr[NOLIGHT], // SPR_ARCH - &lspr[NOLIGHT], // SPR_CBFS - &lspr[NOLIGHT], // SPR_SPSH - &lspr[NOLIGHT], // SPR_ESHI - &lspr[NOLIGHT], // SPR_GSNP - &lspr[NOLIGHT], // SPR_MNUS - &lspr[NOLIGHT], // SPR_SSHL - &lspr[NOLIGHT], // SPR_UNID - &lspr[NOLIGHT], // SPR_BBUZ - - // Generic Boos Items - &lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes - - // Boss 1, (Greenflower) - &lspr[NOLIGHT], // SPR_EGGM - - // Boss 2, (Techno Hill) - &lspr[NOLIGHT], // SPR_EGGN - &lspr[NOLIGHT], // SPR_TNKA - &lspr[NOLIGHT], // SPR_TNKB - &lspr[NOLIGHT], // SPR_SPNK - &lspr[NOLIGHT], // SPR_GOOP - - // Boss 3 (Deep Sea) - &lspr[NOLIGHT], // SPR_EGGO - &lspr[NOLIGHT], // SPR_PRPL - &lspr[NOLIGHT], // SPR_FAKE - - // Boss 4 (Castle Eggman) - &lspr[NOLIGHT], // SPR_EGGP - &lspr[REDBALL_L], // SPR_EFIR - - // Boss 5 (Arid Canyon) - &lspr[NOLIGHT], // SPR_EGGQ - - // 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_EMMY - &lspr[BLUEBALL_L], // SPR_TOKE - &lspr[REDBALL_L], // SPR_RFLG - &lspr[BLUEBALL_L], // SPR_BFLG - &lspr[NOLIGHT], // SPR_NWNG - &lspr[NOLIGHT], // SPR_EMBM - &lspr[NOLIGHT], // SPR_CEMG - &lspr[NOLIGHT], // SPR_EMER - - // Interactive Objects - &lspr[NOLIGHT], // SPR_FANS - &lspr[NOLIGHT], // SPR_BUBL - &lspr[NOLIGHT], // SPR_SIGN - &lspr[NOLIGHT], // SPR_STEM - &lspr[NOLIGHT], // SPR_SPIK - &lspr[NOLIGHT], // SPR_SFLM - &lspr[NOLIGHT], // SPR_USPK - &lspr[NOLIGHT], // SPR_STPT - &lspr[NOLIGHT], // SPR_BMNE - - // Monitor Boxes - &lspr[NOLIGHT], // SPR_SRBX - &lspr[NOLIGHT], // SPR_RRBX - &lspr[NOLIGHT], // SPR_BRBX - &lspr[NOLIGHT], // SPR_SHTV - &lspr[NOLIGHT], // SPR_PINV - &lspr[NOLIGHT], // SPR_YLTV - &lspr[NOLIGHT], // SPR_BLTV - &lspr[NOLIGHT], // SPR_BKTV - &lspr[NOLIGHT], // SPR_WHTV - &lspr[NOLIGHT], // SPR_GRTV - &lspr[NOLIGHT], // SPR_ELTV - &lspr[NOLIGHT], // SPR_EGGB - &lspr[NOLIGHT], // SPR_MIXU - &lspr[NOLIGHT], // SPR_RECY - &lspr[NOLIGHT], // SPR_QUES - &lspr[NOLIGHT], // SPR_GBTV - &lspr[NOLIGHT], // SPR_PRUP - &lspr[NOLIGHT], // SPR_PTTV - - // Monitor Miscellany - &lspr[NOLIGHT], // SPR_MTEX - - // Projectiles - &lspr[NOLIGHT], // SPR_MISL - &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 - - // Techno Hill Scenery - &lspr[NOLIGHT], // SPR_THZP - &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 - - // Arid Canyon Scenery - &lspr[NOLIGHT], // SPR_BTBL - &lspr[NOLIGHT], // SPR_STBL - &lspr[NOLIGHT], // SPR_CACT - - // Red Volcano Scenery - &lspr[REDBALL_L], // SPR_FLME - &lspr[REDBALL_L], // SPR_DFLM - - // Dark City Scenery - - // Egg Rock Scenery - - // Christmas Scenery - &lspr[NOLIGHT], // SPR_XMS1 - &lspr[NOLIGHT], // SPR_XMS2 - &lspr[NOLIGHT], // SPR_XMS3 - - // Botanic Serenity Scenery - &lspr[NOLIGHT], // SPR_BSZ1 - &lspr[NOLIGHT], // SPR_BSZ2 - &lspr[NOLIGHT], // SPR_BSZ3 - &lspr[NOLIGHT], // SPR_BSZ4 - &lspr[NOLIGHT], // SPR_BSZ5 - &lspr[NOLIGHT], // SPR_BSZ6 - &lspr[NOLIGHT], // SPR_BSZ7 - &lspr[NOLIGHT], // SPR_BSZ8 - - // Stalagmites - &lspr[NOLIGHT], // SPR_STLG - - // Disco Ball - &lspr[NOLIGHT], // SPR_DBAL - - // ATZ Red Crystal - &lspr[NOLIGHT], // SPR_RCRY - - // 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[INVINCIBLE_L], // SPR_IVSP - &lspr[SUPERSPARK_L], // SPR_SSPK - - &lspr[NOLIGHT], // SPR_GOAL - - // Freed Animals - &lspr[NOLIGHT], // SPR_BIRD - &lspr[NOLIGHT], // SPR_BUNY - &lspr[NOLIGHT], // SPR_MOUS - &lspr[NOLIGHT], // SPR_CHIC - &lspr[NOLIGHT], // SPR_COWZ - &lspr[NOLIGHT], // SPR_RBRD - - // Springs - &lspr[NOLIGHT], // SPR_SPRY - &lspr[NOLIGHT], // SPR_SPRR - &lspr[NOLIGHT], // SPR_SPRB Graue - &lspr[NOLIGHT], // SPR_YSPR - &lspr[NOLIGHT], // SPR_RSPR - - // Environmentals Effects - &lspr[NOLIGHT], // SPR_RAIN - &lspr[NOLIGHT], // SPR_SNO1 - &lspr[NOLIGHT], // SPR_SPLH - &lspr[NOLIGHT], // SPR_SPLA - &lspr[NOLIGHT], // SPR_SMOK - &lspr[NOLIGHT], // SPR_BUBP - &lspr[NOLIGHT], // SPR_BUBO - &lspr[NOLIGHT], // SPR_BUBN - &lspr[NOLIGHT], // SPR_BUBM - &lspr[NOLIGHT], // SPR_POPP - &lspr[SUPERSPARK_L], // SPR_TFOG - &lspr[NIGHTSLIGHT_L], // SPR_SEED // Sonic CD flower seed - &lspr[NOLIGHT], // SPR_PRTL - - // Game Indicators - &lspr[NOLIGHT], // SPR_SCOR - &lspr[NOLIGHT], // SPR_DRWN - &lspr[NOLIGHT], // SPR_TTAG - &lspr[NOLIGHT], // SPR_GFLG - - // 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[SUPERSONIC_L], // SPR_SUPE // NiGHTS character flying - &lspr[SUPERSONIC_L], // SPR_SUPZ // NiGHTS hurt - &lspr[SUPERSONIC_L], // SPR_NDRL // NiGHTS character drilling - &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[SUPERSONIC_L], // SPR_SUPT - - // Debris - &lspr[RINGSPARK_L], // SPR_SPRK - &lspr[NOLIGHT], // SPR_BOM1 - &lspr[SUPERSPARK_L], // SPR_BOM2 - &lspr[SUPERSPARK_L], // SPR_BOM3 - &lspr[NOLIGHT], // SPR_BOM4 - - // 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 - - // Blue Spheres - &lspr[NOLIGHT], // SPR_BBAL - - // Gravity Well Objects - &lspr[NOLIGHT], // SPR_GWLG - &lspr[NOLIGHT], // SPR_GWLR - - // SRB1 Sprites - &lspr[NOLIGHT], // SPR_SRBA - &lspr[NOLIGHT], // SPR_SRBB - &lspr[NOLIGHT], // SPR_SRBC - &lspr[NOLIGHT], // SPR_SRBD - &lspr[NOLIGHT], // SPR_SRBE - &lspr[NOLIGHT], // SPR_SRBF - &lspr[NOLIGHT], // SPR_SRBG - &lspr[NOLIGHT], // SPR_SRBH - &lspr[NOLIGHT], // SPR_SRBI - &lspr[NOLIGHT], // SPR_SRBJ - &lspr[NOLIGHT], // SPR_SRBK - &lspr[NOLIGHT], // SPR_SRBL - &lspr[NOLIGHT], // SPR_SRBM - &lspr[NOLIGHT], // SPR_SRBN - &lspr[NOLIGHT], // SPR_SRBO - - &lspr[NOLIGHT], //"SPRG", - &lspr[NOLIGHT], //"BSPR", - - &lspr[NOLIGHT], //"RNDM", - &lspr[NOLIGHT], //"KFRE", - &lspr[NOLIGHT], //"DRIF", - &lspr[NOLIGHT], //"DSMO", - - &lspr[NOLIGHT], //"FITM", - &lspr[NOLIGHT], //"BANA", - &lspr[NOLIGHT], //"GSHE", - &lspr[NOLIGHT], //"RSHE", - &lspr[NOLIGHT], //"SSMN", - &lspr[NOLIGHT], //"BLIG", - &lspr[NOLIGHT], //"LIGH", - &lspr[NOLIGHT], //"SINK", - &lspr[NOLIGHT], //"SITR", - &lspr[NOLIGHT], //"KBLN", - - &lspr[NOLIGHT], //"LAKI", - - &lspr[NOLIGHT], //"POKE", - &lspr[NOLIGHT], //"AUDI", - &lspr[NOLIGHT], //"DECO", - &lspr[NOLIGHT], //"DOOD", - &lspr[NOLIGHT], //"SNES", - &lspr[NOLIGHT], //"GBAS", - &lspr[NOLIGHT], //"SPRS", - &lspr[NOLIGHT], //"BUZB", - &lspr[NOLIGHT], //"CHOM", - &lspr[NOLIGHT], //"SACO", - &lspr[NOLIGHT], //"CRAB", - &lspr[NOLIGHT], //"SHAD", - - &lspr[NOLIGHT], //"BUMP", - &lspr[NOLIGHT], //"FLEN", - &lspr[NOLIGHT], //"CLAS", - &lspr[NOLIGHT], //"PSHW", - - &lspr[NOLIGHT], //"ARRO", - - &lspr[NOLIGHT], //"PBOM" - - // 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_grdynamiclighting.value is not set - for (j = 0; j < dynlights->nb; j++) - { - FVector inter; - FSurfaceInfo Surf; - float dist_p2d, d[4], s; - - // 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].sow = (float)(0.5f + d[i]*s); - wlVerts[i].tow = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f); - } - - HWR_SetLight(); - - Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); -#ifdef DL_HIGH_QUALITY - Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); -#endif - if (!dynlights->mo[j]->state) - return; - // next state is null so fade out with alpha - if (dynlights->mo[j]->state->nextstate == S_NULL) - Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.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; - - // 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].sow = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s; - clVerts[i].tow = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f; - } - - HWR_SetLight(); - - Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); -#ifdef DL_HIGH_QUALITY - Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); -#endif - if (!dynlights->mo[j]->state) - return; - // next state is null so fade out with alpha - if ((dynlights->mo[j]->state->nextstate == S_NULL)) - Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.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, gr_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_grcoronas.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_grcoronasize.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.FlatColor.rgba = p_lspr->corona_color; - if (cz > 250.0f) - Surf.FlatColor.s.alpha = 0xff-((int)cz-250)/8; - else - Surf.FlatColor.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].sow = 0.0f; light[0].tow = 0.0f; - - light[1].x = cx+size; light[1].z = cz; - light[1].y = cy-size*1.33f+p_lspr->light_yoffset; - light[1].sow = 1.0f; light[1].tow = 0.0f; - - light[2].x = cx+size; light[2].z = cz; - light[2].y = cy+size*1.33f+p_lspr->light_yoffset; - light[2].sow = 1.0f; light[2].tow = 1.0f; - - light[3].x = cx-size; light[3].z = cz; - light[3].y = cy+size*1.33f+p_lspr->light_yoffset; - light[3].sow = 0.0f; light[3].tow = 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_grcoronas.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; - - transform(&cx,&cy,&cz); - - // more realistique corona ! - if (cz >= 255*8+250) - continue; - Surf.FlatColor.rgba = p_lspr->corona_color; - if (cz > 250.0f) - Surf.FlatColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8)); - else - Surf.FlatColor.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.FlatColor.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_grcoronasize.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].sow = 0.0f; light[0].tow = 0.0f; - - light[1].x = cx+size; light[1].z = cz; - light[1].y = cy-size*1.33f; - light[1].sow = 1.0f; light[1].tow = 0.0f; - - light[2].x = cx+size; light[2].z = cz; - light[2].y = cy+size*1.33f; - light[2].sow = 1.0f; light[2].tow = 1.0f; - - light[3].x = cx-size; light[3].z = cz; - light[3].y = cy+size*1.33f; - light[3].sow = 0.0f; light[3].tow = 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) -{ - dynlights->nb = 0; -} - -// -------------------------------------------------------------------------- -// 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(gr_vissprite_t *spr, GLPatch_t *patch) -{ - light_t *p_lspr; - - //Hurdler: moved here because it's better;-) - (void)patch; - if (!cv_grdynamiclighting.value) - return; - - if (!spr->mobj) -#ifdef PARANOIA - I_Error("vissprite without mobj !!!"); -#else - return; -#endif - - // check if sprite contain dynamic light - p_lspr = t_lspr[spr->mobj->sprite]; - if ((p_lspr->type&DYNLIGHT_SPR) - && ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) - && (dynlights->nb < DL_MAX_LIGHT) - - && spr->mobj->state) - { - 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 GLPatch_t lightmappatch; - -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.grInfo.data) - { - - UINT16 *Data = Z_Malloc(129*128*sizeof (UINT16), PU_HWRCACHE, &lightmappatch.mipmap.grInfo.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.grInfo.format = GR_TEXFMT_ALPHA_INTENSITY_88; - - lightmappatch.width = 128; - lightmappatch.height = 128; - lightmappatch.mipmap.width = 128; - lightmappatch.mipmap.height = 128; - lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128; - lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128; - lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; - 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.grInfo.data, PU_HWRCACHE_UNLOCKED); -} - -//********************************************************** -// Hurdler: new code for faster static lighting and and T&L -//********************************************************** - -#ifdef STATICLIGHT -// is this really necessary? -static sector_t *lgr_backsector; -static seg_t *lgr_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; - - lgr_curline = line; - lgr_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 ( lgr_backsector->ceilingpic == gr_frontsector->ceilingpic - && lgr_backsector->floorpic == gr_frontsector->floorpic - && lgr_backsector->lightlevel == gr_frontsector->lightlevel - && lgr_curline->sidedef->midtexture == 0) - { - return; - } -*/ - - p1.y = FIXED_TO_FLOAT(lgr_curline->v1->y); - p1.x = FIXED_TO_FLOAT(lgr_curline->v1->x); - p2.y = FIXED_TO_FLOAT(lgr_curline->v2->y); - p2.x = FIXED_TO_FLOAT(lgr_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; - - 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 (t_lspr[thing->sprite]->type & CORONA_SPR) - { - 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); - - dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; - - dynlights->nb++; - if (dynlights->nb > DL_MAX_LIGHT) - dynlights->nb = DL_MAX_LIGHT; - } -} - -//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 = thinkercap.next; th != &thinkercap; th = th->next) - { - // a mobj ? - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - HWR_AddMobjLights((mobj_t *)th); - } -} -#endif - -// -// HWR_CreateStaticLightmaps() -// -void HWR_CreateStaticLightmaps(int bspnum) -{ -#ifdef STATICLIGHT - CONS_Debug(DBG_RENDER, "HWR_CreateStaticLightmaps\n"); - - dynlights->nb = 0; - - // 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); - - dynlights->nb = 0; -#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 2733cc69..fbc1d1f2 100644 --- a/src/hardware/hw_light.h +++ b/src/hardware/hw_light.h @@ -1,17 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief Dynamic lighting & coronas add on by Hurdler @@ -22,79 +17,4 @@ #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(gr_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, gr_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 6a08b1c7..1bad26ee 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,17 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief hardware renderer, using the standard HardWareRender driver DLL for SRB2 @@ -21,16 +16,20 @@ #include "../doomstat.h" #ifdef HWRENDER +#include "hw_main.h" #include "hw_glob.h" -#include "hw_light.h" #include "hw_drv.h" +#include "hw_md2.h" +#include "hw_clip.h" +#include "hw_light.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" +#include "../r_bsp.h" // R_NoEncore +#include "../r_main.h" // cv_fov #include "../d_clisrv.h" #include "../w_wad.h" #include "../z_zone.h" @@ -39,19 +38,14 @@ #include "../st_stuff.h" #include "../i_system.h" #include "../m_cheat.h" + #ifdef ESLOPE #include "../p_slopes.h" #endif -#include "hw_md2.h" -#ifdef NEWCLIP -#include "hw_clip.h" -#endif +#include // qsort -#define R_FAKEFLOORS -#define HWPRECIP -#define SORTING -//#define POLYSKY +#define ABS(x) ((x) < 0 ? -(x) : (x)) // ========================================================================== // the hardware driver object @@ -59,36 +53,11 @@ struct hwdriver_s hwdriver; // ========================================================================== -// PROTOS +// Commands and console variables // ========================================================================== - -static void HWR_AddSprites(sector_t *sec); -static void HWR_ProjectSprite(mobj_t *thing); -#ifdef HWPRECIP -static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); -#endif - -#ifdef SORTING -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_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, - INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); -#else -static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, - INT32 lightlevel, INT32 alpha, sector_t *FOFSector); -static void HWR_Render3DWater(void); -static void HWR_RenderTransparentWalls(void); -#endif -static void HWR_FoggingOn(void); -static UINT32 atohex(const char *s); - static void CV_filtermode_ONChange(void); static void CV_anisotropic_ONChange(void); -static void CV_FogDensity_ONChange(void); -// ========================================================================== -// 3D ENGINE COMMANDS & CONSOLE VARS -// ========================================================================== static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, @@ -98,34 +67,17 @@ static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA {0, NULL}}; CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; -boolean drawsky = true; - -// needs fix: walls are incorrectly clipped one column less -#ifndef NEWCLIP -static consvar_t cv_grclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif -//development variables for diverse uses -static consvar_t cv_gralpha = {"gr_alpha", "160", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_grbeta = {"gr_beta", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; - -static float HWRWipeCounter = 1.0f; consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned, - CV_FogDensity_ONChange, 0, NULL, NULL, 0, 0, NULL}; -// Unfortunately, this can no longer be saved.. -consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_CALL, grfiltermode_cons_t, + +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, granisotropicmode_cons_t, +consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL|CV_SAVE, granisotropicmode_cons_t, CV_anisotropic_ONChange, 0, NULL, NULL, 0, 0, NULL}; -//static consvar_t cv_grzbuffer = {"gr_zbuffer", "On", 0, CV_OnOff}; 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}; -static void CV_FogDensity_ONChange(void) -{ - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); -} +consvar_t cv_grbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static void CV_filtermode_ONChange(void) { @@ -137,193 +89,9 @@ static void CV_anisotropic_ONChange(void) HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); } -/* - * lookuptable for lightvalues - * calculated as follow: - * floatlight = (1.0-exp((light^3)*gamma)) / (1.0-exp(1.0*gamma)); - * gamma=-0,2;-2,0;-4,0;-6,0;-8,0 - * light = 0,0 .. 1,0 - */ -static const float lighttable[5][256] = -{ - { - 0.00000f,0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00001f,0.00002f,0.00003f,0.00004f, - 0.00006f,0.00008f,0.00010f,0.00013f,0.00017f,0.00020f,0.00025f,0.00030f,0.00035f,0.00041f, - 0.00048f,0.00056f,0.00064f,0.00073f,0.00083f,0.00094f,0.00106f,0.00119f,0.00132f,0.00147f, - 0.00163f,0.00180f,0.00198f,0.00217f,0.00237f,0.00259f,0.00281f,0.00305f,0.00331f,0.00358f, - 0.00386f,0.00416f,0.00447f,0.00479f,0.00514f,0.00550f,0.00587f,0.00626f,0.00667f,0.00710f, - 0.00754f,0.00800f,0.00848f,0.00898f,0.00950f,0.01003f,0.01059f,0.01117f,0.01177f,0.01239f, - 0.01303f,0.01369f,0.01437f,0.01508f,0.01581f,0.01656f,0.01734f,0.01814f,0.01896f,0.01981f, - 0.02069f,0.02159f,0.02251f,0.02346f,0.02444f,0.02544f,0.02647f,0.02753f,0.02862f,0.02973f, - 0.03088f,0.03205f,0.03325f,0.03448f,0.03575f,0.03704f,0.03836f,0.03971f,0.04110f,0.04252f, - 0.04396f,0.04545f,0.04696f,0.04851f,0.05009f,0.05171f,0.05336f,0.05504f,0.05676f,0.05852f, - 0.06031f,0.06214f,0.06400f,0.06590f,0.06784f,0.06981f,0.07183f,0.07388f,0.07597f,0.07810f, - 0.08027f,0.08248f,0.08473f,0.08702f,0.08935f,0.09172f,0.09414f,0.09659f,0.09909f,0.10163f, - 0.10421f,0.10684f,0.10951f,0.11223f,0.11499f,0.11779f,0.12064f,0.12354f,0.12648f,0.12946f, - 0.13250f,0.13558f,0.13871f,0.14188f,0.14511f,0.14838f,0.15170f,0.15507f,0.15850f,0.16197f, - 0.16549f,0.16906f,0.17268f,0.17635f,0.18008f,0.18386f,0.18769f,0.19157f,0.19551f,0.19950f, - 0.20354f,0.20764f,0.21179f,0.21600f,0.22026f,0.22458f,0.22896f,0.23339f,0.23788f,0.24242f, - 0.24702f,0.25168f,0.25640f,0.26118f,0.26602f,0.27091f,0.27587f,0.28089f,0.28596f,0.29110f, - 0.29630f,0.30156f,0.30688f,0.31226f,0.31771f,0.32322f,0.32879f,0.33443f,0.34013f,0.34589f, - 0.35172f,0.35761f,0.36357f,0.36960f,0.37569f,0.38185f,0.38808f,0.39437f,0.40073f,0.40716f, - 0.41366f,0.42022f,0.42686f,0.43356f,0.44034f,0.44718f,0.45410f,0.46108f,0.46814f,0.47527f, - 0.48247f,0.48974f,0.49709f,0.50451f,0.51200f,0.51957f,0.52721f,0.53492f,0.54271f,0.55058f, - 0.55852f,0.56654f,0.57463f,0.58280f,0.59105f,0.59937f,0.60777f,0.61625f,0.62481f,0.63345f, - 0.64217f,0.65096f,0.65984f,0.66880f,0.67783f,0.68695f,0.69615f,0.70544f,0.71480f,0.72425f, - 0.73378f,0.74339f,0.75308f,0.76286f,0.77273f,0.78268f,0.79271f,0.80283f,0.81304f,0.82333f, - 0.83371f,0.84417f,0.85472f,0.86536f,0.87609f,0.88691f,0.89781f,0.90880f,0.91989f,0.93106f, - 0.94232f,0.95368f,0.96512f,0.97665f,0.98828f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00007f,0.00010f, - 0.00014f,0.00019f,0.00024f,0.00031f,0.00038f,0.00047f,0.00057f,0.00069f,0.00081f,0.00096f, - 0.00112f,0.00129f,0.00148f,0.00170f,0.00193f,0.00218f,0.00245f,0.00274f,0.00306f,0.00340f, - 0.00376f,0.00415f,0.00456f,0.00500f,0.00547f,0.00597f,0.00649f,0.00704f,0.00763f,0.00825f, - 0.00889f,0.00957f,0.01029f,0.01104f,0.01182f,0.01264f,0.01350f,0.01439f,0.01532f,0.01630f, - 0.01731f,0.01836f,0.01945f,0.02058f,0.02176f,0.02298f,0.02424f,0.02555f,0.02690f,0.02830f, - 0.02974f,0.03123f,0.03277f,0.03436f,0.03600f,0.03768f,0.03942f,0.04120f,0.04304f,0.04493f, - 0.04687f,0.04886f,0.05091f,0.05301f,0.05517f,0.05738f,0.05964f,0.06196f,0.06434f,0.06677f, - 0.06926f,0.07181f,0.07441f,0.07707f,0.07979f,0.08257f,0.08541f,0.08831f,0.09126f,0.09428f, - 0.09735f,0.10048f,0.10368f,0.10693f,0.11025f,0.11362f,0.11706f,0.12056f,0.12411f,0.12773f, - 0.13141f,0.13515f,0.13895f,0.14281f,0.14673f,0.15072f,0.15476f,0.15886f,0.16303f,0.16725f, - 0.17153f,0.17587f,0.18028f,0.18474f,0.18926f,0.19383f,0.19847f,0.20316f,0.20791f,0.21272f, - 0.21759f,0.22251f,0.22748f,0.23251f,0.23760f,0.24274f,0.24793f,0.25318f,0.25848f,0.26383f, - 0.26923f,0.27468f,0.28018f,0.28573f,0.29133f,0.29697f,0.30266f,0.30840f,0.31418f,0.32001f, - 0.32588f,0.33179f,0.33774f,0.34374f,0.34977f,0.35585f,0.36196f,0.36810f,0.37428f,0.38050f, - 0.38675f,0.39304f,0.39935f,0.40570f,0.41207f,0.41847f,0.42490f,0.43136f,0.43784f,0.44434f, - 0.45087f,0.45741f,0.46398f,0.47057f,0.47717f,0.48379f,0.49042f,0.49707f,0.50373f,0.51041f, - 0.51709f,0.52378f,0.53048f,0.53718f,0.54389f,0.55061f,0.55732f,0.56404f,0.57075f,0.57747f, - 0.58418f,0.59089f,0.59759f,0.60429f,0.61097f,0.61765f,0.62432f,0.63098f,0.63762f,0.64425f, - 0.65086f,0.65746f,0.66404f,0.67060f,0.67714f,0.68365f,0.69015f,0.69662f,0.70307f,0.70948f, - 0.71588f,0.72224f,0.72857f,0.73488f,0.74115f,0.74739f,0.75359f,0.75976f,0.76589f,0.77199f, - 0.77805f,0.78407f,0.79005f,0.79599f,0.80189f,0.80774f,0.81355f,0.81932f,0.82504f,0.83072f, - 0.83635f,0.84194f,0.84747f,0.85296f,0.85840f,0.86378f,0.86912f,0.87441f,0.87964f,0.88482f, - 0.88995f,0.89503f,0.90005f,0.90502f,0.90993f,0.91479f,0.91959f,0.92434f,0.92903f,0.93366f, - 0.93824f,0.94276f,0.94723f,0.95163f,0.95598f,0.96027f,0.96451f,0.96868f,0.97280f,0.97686f, - 0.98086f,0.98481f,0.98869f,0.99252f,0.99629f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00008f,0.00013f,0.00018f, - 0.00025f,0.00033f,0.00042f,0.00054f,0.00067f,0.00083f,0.00101f,0.00121f,0.00143f,0.00168f, - 0.00196f,0.00227f,0.00261f,0.00299f,0.00339f,0.00383f,0.00431f,0.00483f,0.00538f,0.00598f, - 0.00661f,0.00729f,0.00802f,0.00879f,0.00961f,0.01048f,0.01140f,0.01237f,0.01340f,0.01447f, - 0.01561f,0.01680f,0.01804f,0.01935f,0.02072f,0.02215f,0.02364f,0.02520f,0.02682f,0.02850f, - 0.03026f,0.03208f,0.03397f,0.03594f,0.03797f,0.04007f,0.04225f,0.04451f,0.04684f,0.04924f, - 0.05172f,0.05428f,0.05691f,0.05963f,0.06242f,0.06530f,0.06825f,0.07129f,0.07441f,0.07761f, - 0.08089f,0.08426f,0.08771f,0.09125f,0.09487f,0.09857f,0.10236f,0.10623f,0.11019f,0.11423f, - 0.11836f,0.12257f,0.12687f,0.13125f,0.13571f,0.14027f,0.14490f,0.14962f,0.15442f,0.15931f, - 0.16427f,0.16932f,0.17445f,0.17966f,0.18496f,0.19033f,0.19578f,0.20130f,0.20691f,0.21259f, - 0.21834f,0.22417f,0.23007f,0.23605f,0.24209f,0.24820f,0.25438f,0.26063f,0.26694f,0.27332f, - 0.27976f,0.28626f,0.29282f,0.29944f,0.30611f,0.31284f,0.31962f,0.32646f,0.33334f,0.34027f, - 0.34724f,0.35426f,0.36132f,0.36842f,0.37556f,0.38273f,0.38994f,0.39718f,0.40445f,0.41174f, - 0.41907f,0.42641f,0.43378f,0.44116f,0.44856f,0.45598f,0.46340f,0.47084f,0.47828f,0.48573f, - 0.49319f,0.50064f,0.50809f,0.51554f,0.52298f,0.53042f,0.53784f,0.54525f,0.55265f,0.56002f, - 0.56738f,0.57472f,0.58203f,0.58932f,0.59658f,0.60381f,0.61101f,0.61817f,0.62529f,0.63238f, - 0.63943f,0.64643f,0.65339f,0.66031f,0.66717f,0.67399f,0.68075f,0.68746f,0.69412f,0.70072f, - 0.70726f,0.71375f,0.72017f,0.72653f,0.73282f,0.73905f,0.74522f,0.75131f,0.75734f,0.76330f, - 0.76918f,0.77500f,0.78074f,0.78640f,0.79199f,0.79751f,0.80295f,0.80831f,0.81359f,0.81880f, - 0.82393f,0.82898f,0.83394f,0.83883f,0.84364f,0.84836f,0.85301f,0.85758f,0.86206f,0.86646f, - 0.87078f,0.87502f,0.87918f,0.88326f,0.88726f,0.89118f,0.89501f,0.89877f,0.90245f,0.90605f, - 0.90957f,0.91301f,0.91638f,0.91966f,0.92288f,0.92601f,0.92908f,0.93206f,0.93498f,0.93782f, - 0.94059f,0.94329f,0.94592f,0.94848f,0.95097f,0.95339f,0.95575f,0.95804f,0.96027f,0.96244f, - 0.96454f,0.96658f,0.96856f,0.97049f,0.97235f,0.97416f,0.97591f,0.97760f,0.97924f,0.98083f, - 0.98237f,0.98386f,0.98530f,0.98669f,0.98803f,0.98933f,0.99058f,0.99179f,0.99295f,0.99408f, - 0.99516f,0.99620f,0.99721f,0.99817f,0.99910f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00005f,0.00008f,0.00012f,0.00019f,0.00026f, - 0.00036f,0.00048f,0.00063f,0.00080f,0.00099f,0.00122f,0.00148f,0.00178f,0.00211f,0.00249f, - 0.00290f,0.00335f,0.00386f,0.00440f,0.00500f,0.00565f,0.00636f,0.00711f,0.00793f,0.00881f, - 0.00975f,0.01075f,0.01182f,0.01295f,0.01416f,0.01543f,0.01678f,0.01821f,0.01971f,0.02129f, - 0.02295f,0.02469f,0.02652f,0.02843f,0.03043f,0.03252f,0.03469f,0.03696f,0.03933f,0.04178f, - 0.04433f,0.04698f,0.04973f,0.05258f,0.05552f,0.05857f,0.06172f,0.06498f,0.06834f,0.07180f, - 0.07537f,0.07905f,0.08283f,0.08672f,0.09072f,0.09483f,0.09905f,0.10337f,0.10781f,0.11236f, - 0.11701f,0.12178f,0.12665f,0.13163f,0.13673f,0.14193f,0.14724f,0.15265f,0.15817f,0.16380f, - 0.16954f,0.17538f,0.18132f,0.18737f,0.19351f,0.19976f,0.20610f,0.21255f,0.21908f,0.22572f, - 0.23244f,0.23926f,0.24616f,0.25316f,0.26023f,0.26739f,0.27464f,0.28196f,0.28935f,0.29683f, - 0.30437f,0.31198f,0.31966f,0.32740f,0.33521f,0.34307f,0.35099f,0.35896f,0.36699f,0.37506f, - 0.38317f,0.39133f,0.39952f,0.40775f,0.41601f,0.42429f,0.43261f,0.44094f,0.44929f,0.45766f, - 0.46604f,0.47443f,0.48283f,0.49122f,0.49962f,0.50801f,0.51639f,0.52476f,0.53312f,0.54146f, - 0.54978f,0.55807f,0.56633f,0.57457f,0.58277f,0.59093f,0.59905f,0.60713f,0.61516f,0.62314f, - 0.63107f,0.63895f,0.64676f,0.65452f,0.66221f,0.66984f,0.67739f,0.68488f,0.69229f,0.69963f, - 0.70689f,0.71407f,0.72117f,0.72818f,0.73511f,0.74195f,0.74870f,0.75536f,0.76192f,0.76839f, - 0.77477f,0.78105f,0.78723f,0.79331f,0.79930f,0.80518f,0.81096f,0.81664f,0.82221f,0.82768f, - 0.83305f,0.83832f,0.84347f,0.84853f,0.85348f,0.85832f,0.86306f,0.86770f,0.87223f,0.87666f, - 0.88098f,0.88521f,0.88933f,0.89334f,0.89726f,0.90108f,0.90480f,0.90842f,0.91194f,0.91537f, - 0.91870f,0.92193f,0.92508f,0.92813f,0.93109f,0.93396f,0.93675f,0.93945f,0.94206f,0.94459f, - 0.94704f,0.94941f,0.95169f,0.95391f,0.95604f,0.95810f,0.96009f,0.96201f,0.96386f,0.96564f, - 0.96735f,0.96900f,0.97059f,0.97212f,0.97358f,0.97499f,0.97634f,0.97764f,0.97888f,0.98007f, - 0.98122f,0.98231f,0.98336f,0.98436f,0.98531f,0.98623f,0.98710f,0.98793f,0.98873f,0.98949f, - 0.99021f,0.99090f,0.99155f,0.99218f,0.99277f,0.99333f,0.99387f,0.99437f,0.99486f,0.99531f, - 0.99575f,0.99616f,0.99654f,0.99691f,0.99726f,0.99759f,0.99790f,0.99819f,0.99847f,0.99873f, - 0.99897f,0.99920f,0.99942f,0.99963f,0.99982f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00003f,0.00006f,0.00010f,0.00017f,0.00025f,0.00035f, - 0.00048f,0.00064f,0.00083f,0.00106f,0.00132f,0.00163f,0.00197f,0.00237f,0.00281f,0.00330f, - 0.00385f,0.00446f,0.00513f,0.00585f,0.00665f,0.00751f,0.00845f,0.00945f,0.01054f,0.01170f, - 0.01295f,0.01428f,0.01569f,0.01719f,0.01879f,0.02048f,0.02227f,0.02415f,0.02614f,0.02822f, - 0.03042f,0.03272f,0.03513f,0.03765f,0.04028f,0.04303f,0.04589f,0.04887f,0.05198f,0.05520f, - 0.05855f,0.06202f,0.06561f,0.06933f,0.07318f,0.07716f,0.08127f,0.08550f,0.08987f,0.09437f, - 0.09900f,0.10376f,0.10866f,0.11369f,0.11884f,0.12414f,0.12956f,0.13512f,0.14080f,0.14662f, - 0.15257f,0.15865f,0.16485f,0.17118f,0.17764f,0.18423f,0.19093f,0.19776f,0.20471f,0.21177f, - 0.21895f,0.22625f,0.23365f,0.24117f,0.24879f,0.25652f,0.26435f,0.27228f,0.28030f,0.28842f, - 0.29662f,0.30492f,0.31329f,0.32175f,0.33028f,0.33889f,0.34756f,0.35630f,0.36510f,0.37396f, - 0.38287f,0.39183f,0.40084f,0.40989f,0.41897f,0.42809f,0.43723f,0.44640f,0.45559f,0.46479f, - 0.47401f,0.48323f,0.49245f,0.50167f,0.51088f,0.52008f,0.52927f,0.53843f,0.54757f,0.55668f, - 0.56575f,0.57479f,0.58379f,0.59274f,0.60164f,0.61048f,0.61927f,0.62799f,0.63665f,0.64524f, - 0.65376f,0.66220f,0.67056f,0.67883f,0.68702f,0.69511f,0.70312f,0.71103f,0.71884f,0.72655f, - 0.73415f,0.74165f,0.74904f,0.75632f,0.76348f,0.77053f,0.77747f,0.78428f,0.79098f,0.79756f, - 0.80401f,0.81035f,0.81655f,0.82264f,0.82859f,0.83443f,0.84013f,0.84571f,0.85117f,0.85649f, - 0.86169f,0.86677f,0.87172f,0.87654f,0.88124f,0.88581f,0.89026f,0.89459f,0.89880f,0.90289f, - 0.90686f,0.91071f,0.91445f,0.91807f,0.92157f,0.92497f,0.92826f,0.93143f,0.93450f,0.93747f, - 0.94034f,0.94310f,0.94577f,0.94833f,0.95081f,0.95319f,0.95548f,0.95768f,0.95980f,0.96183f, - 0.96378f,0.96565f,0.96744f,0.96916f,0.97081f,0.97238f,0.97388f,0.97532f,0.97669f,0.97801f, - 0.97926f,0.98045f,0.98158f,0.98266f,0.98369f,0.98467f,0.98560f,0.98648f,0.98732f,0.98811f, - 0.98886f,0.98958f,0.99025f,0.99089f,0.99149f,0.99206f,0.99260f,0.99311f,0.99359f,0.99404f, - 0.99446f,0.99486f,0.99523f,0.99559f,0.99592f,0.99623f,0.99652f,0.99679f,0.99705f,0.99729f, - 0.99751f,0.99772f,0.99792f,0.99810f,0.99827f,0.99843f,0.99857f,0.99871f,0.99884f,0.99896f, - 0.99907f,0.99917f,0.99926f,0.99935f,0.99943f,0.99951f,0.99958f,0.99964f,0.99970f,0.99975f, - 0.99980f,0.99985f,0.99989f,0.99993f,0.99997f,1.00000f - } -}; - -#define gld_CalcLightLevel(lightlevel) (lighttable[1][max(min((lightlevel),255),0)]) - // ========================================================================== -// VIEW GLOBALS +// Globals // ========================================================================== -// Fineangles in the SCREENWIDTH wide window. -#define FIELDOFVIEW ANGLE_90 -#define ABS(x) ((x) < 0 ? -(x) : (x)) - -static angle_t gr_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 gr_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 gr_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; @@ -343,187 +111,163 @@ static float gr_windowcentery; static float gr_pspritexscale, gr_pspriteyscale; + 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; -// -------------------------------------------------------------------------- -// STUFF FOR THE PROJECTION CODE -// -------------------------------------------------------------------------- +boolean gr_shadersavailable = true; + +// ========================================================================== +// View position +// ========================================================================== 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; -// Maybe not necessary with the new T&L code (needs to be checked!) -static float gr_viewludsin, gr_viewludcos; // look up down kik test -static float gr_fovlud; +static angle_t gr_aimingangle; +static float gr_viewludsin, gr_viewludcos; + +static INT32 drawcount = 0; // ========================================================================== -// LIGHT stuffs +// Lighting // ========================================================================== -static UINT8 lightleveltonumlut[256]; - -// added to SRB2's sector lightlevel to make things a bit brighter (sprites/walls/planes) -FUNCMATH UINT8 LightLevelToLum(INT32 l) +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap) { - return (UINT8)(255*gld_CalcLightLevel(l)); + RGBA_t poly_color, tint_color, fade_color; + + poly_color.rgba = 0xFFFFFFFF; + tint_color.rgba = (colormap != NULL) ? (UINT32)colormap->rgba : GL_DEFAULTMIX; + 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)) + { + // be careful, this may get negative for high lightlevel values. + float tint_alpha, fade_alpha; + float red, green, blue; + + red = (float)poly_color.s.red; + green = (float)poly_color.s.green; + blue = (float)poly_color.s.blue; + + // 48 is just an arbritrary value that looked relatively okay. + tint_alpha = (float)(sqrt(tint_color.s.alpha) * 48) / 255.0f; + + // 8 is roughly the brightness of the "close" color in Software, and 16 the brightness of the "far" color. + // 8 is too bright for dark levels, and 16 is too dark for bright levels. + // 12 is the compromise value. It doesn't look especially good anywhere, but it's the most balanced. + // (Also, as far as I can tell, fade_color's alpha is actually not used in Software, so we only use light level.) + fade_alpha = (float)(sqrt(255-light_level) * 12) / 255.0f; + + // Clamp the alpha values + tint_alpha = min(max(tint_alpha, 0.0f), 1.0f); + fade_alpha = min(max(fade_alpha, 0.0f), 1.0f); + + red = (tint_color.s.red * tint_alpha) + (red * (1.0f - tint_alpha)); + green = (tint_color.s.green * tint_alpha) + (green * (1.0f - tint_alpha)); + blue = (tint_color.s.blue * tint_alpha) + (blue * (1.0f - tint_alpha)); + + red = (fade_color.s.red * fade_alpha) + (red * (1.0f - fade_alpha)); + green = (fade_color.s.green * fade_alpha) + (green * (1.0f - fade_alpha)); + blue = (fade_color.s.blue * fade_alpha) + (blue * (1.0f - fade_alpha)); + + poly_color.s.red = (UINT8)red; + poly_color.s.green = (UINT8)green; + poly_color.s.blue = (UINT8)blue; + } + + Surface->PolyColor.rgba = poly_color.rgba; + Surface->TintColor.rgba = tint_color.rgba; + Surface->FadeColor.rgba = fade_color.rgba; + Surface->LightInfo.light_level = light_level; + Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0; + Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31; } -static inline void InitLumLut(void) -{ - INT32 i, k = 0; - for (i = 0; i < 256; i++) - { - if (i > 128) - k += 2; - else - k = 1; - lightleveltonumlut[i] = (UINT8)(k); - } -} - -//#define FOGFACTOR 300 //was 600 >> Covered by cv_grfogdensity -#define NORMALFOG 0x00000000 -#define FADEFOG 0x19000000 -#define CALCFOGDENSITY(x) ((float)((5220.0f*(1.0f/((x)/41.0f+1.0f)))-(5220.0f*(1.0f/(255.0f/41.0f+1.0f))))) // Approximate fog calculation based off of software walls -#define CALCFOGDENSITYFLOOR(x) ((float)((40227.0f*(1.0f/((x)/11.0f+1.0f)))-(40227.0f*(1.0f/(255.0f/11.0f+1.0f))))) // Approximate fog calculation based off of software floors -#define CALCLIGHT(x,y) ((float)(x)*((y)/255.0f)) -UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane) -{ - RGBA_t realcolor, fogcolor, surfcolor; - INT32 alpha, fogalpha; - - (void)fogblockpoly; - - // Don't go out of bounds - if (light < 0) - light = 0; - else if (light > 255) - light = 255; - - realcolor.rgba = color; - fogcolor.rgba = fadecolor; - - alpha = (realcolor.s.alpha*255)/25; - fogalpha = (fogcolor.s.alpha*255)/25; - - if (cv_grfog.value && cv_grsoftwarefog.value) // Only do this when fog is on, software fog mode is on, and the poly is not from a fog block - { - // Modulate the colors by alpha. - realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red)); - realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green)); - realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue)); - - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.red,255)); - surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.green,255)); - surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.blue,255)); - surfcolor.s.alpha = 0xFF; - - // Modulate the colors by alpha. - fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red)); - fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green)); - fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue)); - } - else - { - // Modulate the colors by alpha. - realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red)); - realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green)); - realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue)); - - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.red,light)); - surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.green,light)); - surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.blue,light)); - - // Modulate the colors by alpha. - fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red)); - fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green)); - fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue)); - - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = surfcolor.s.red+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.red,(255-light)))); - surfcolor.s.green = surfcolor.s.green+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.green,(255-light)))); - surfcolor.s.blue = surfcolor.s.blue+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.blue,(255-light)))); - surfcolor.s.alpha = 0xFF; - } - - if(cv_grfog.value) - { - if (cv_grsoftwarefog.value) - { - fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light))); - fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light))); - fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light))); - - // Set the fog options. - if (cv_grsoftwarefog.value == 1 && plane) // With floors, software draws them way darker for their distance - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITYFLOOR(light))); - else // everything else is drawn like walls - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITY(light))); - } - else - { - fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light))); - fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light))); - fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light))); - - fogalpha = (UINT8)((CALCLIGHT(fogalpha,(255-light)))+(CALCLIGHT(alpha,light))); - - // Set the fog options. - light = (UINT8)(CALCLIGHT(light,(255-fogalpha))); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(cv_grfogdensity.value-(cv_grfogdensity.value*(float)light/255.0f))); - } - - HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, (fogcolor.s.red*0x10000)+(fogcolor.s.green*0x100)+fogcolor.s.blue); - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1); - } - return surfcolor.rgba; -} - - -static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this can work +UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work { RGBA_t realcolor, surfcolor; INT32 alpha; - // Don't go out of bounds - if (light < 0) - light = 0; - else if (light > 255) - light = 255; + realcolor.rgba = (colormap != NULL) ? colormap->rgba : GL_DEFAULTMIX; - realcolor.rgba = color; + if (!(cv_grshaders.value && gr_shadersavailable)) + { + light = light - (255 - light); - alpha = (realcolor.s.alpha*255)/25; + // Don't go out of bounds + if (light < 0) + light = 0; + else if (light > 255) + light = 255; - // 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; + alpha = (realcolor.s.alpha*255)/25; + + // 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; } +static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) +{ + INT16 finallight = lightnum; + + if (cv_grfakecontrast.value != 0) + { + const UINT8 contrast = 8; + fixed_t extralight = 0; + + if (cv_grfakecontrast.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; +} + // ========================================================================== -// FLOOR/CEILING GENERATION FROM SUBSECTORS +// Floor and ceiling generation from subsectors // ========================================================================== -#ifdef DOPLANES - -// -----------------+ -// HWR_RenderPlane : Render a floor or ceiling convex polygon -// -----------------+ -static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) +// 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) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -545,8 +289,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - (void)sector; ///@TODO remove shitty unused variable - // no convex poly were generated for this subsector if (!xsub->planepoly) return; @@ -581,12 +323,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (nrPlaneVerts < 3) //not even a triangle ? return; - if ((UINT32)nrPlaneVerts > UINT16_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) { @@ -667,10 +403,11 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is } } + if (angle) // Only needs to be done if there's an altered angle { - angle = InvAngle(angle)>>ANGLETOFINESHIFT; + angle = (InvAngle(angle)+ANGLE_180)>>ANGLETOFINESHIFT; // This needs to be done so that it scrolls in a different direction after rotation like software /*tempxsow = FLOAT_TO_FIXED(scrollx); @@ -686,26 +423,27 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } + for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly); + v3d->s = (float)((pv->x / fflatsize) - flatxref + scrollx); + v3d->t = (float)(flatyref - (pv->y / fflatsize) + scrolly); - //v3d->sow = (float)(pv->x / fflatsize); - //v3d->tow = (float)(pv->y / fflatsize); + //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->sow); - tempytow = FLOAT_TO_FIXED(v3d->tow); - v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(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->sow = (float)(v3d->sow - flatxref + scrollx); - //v3d->tow = (float)(flatyref - v3d->tow + scrolly); + //v3d->s = (float)(v3d->s - flatxref + scrollx); + //v3d->t = (float)(flatyref - v3d->t + scrolly); v3d->x = pv->x; v3d->y = height; @@ -720,142 +458,33 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is #endif } - // only useful for flat coloured triangles - //Surf.FlatColor = 0xff804020; - - // use different light tables - // for horizontal / vertical / diagonal - // note: try to get the same visual feel as the original - Surf.FlatColor.s.red = Surf.FlatColor.s.green = - Surf.FlatColor.s.blue = LightLevelToLum(lightlevel); // Don't take from the frontsector, or the game will crash - -#if 0 // no colormap test - // colormap test - if (gr_frontsector) - { - sector_t *psector = gr_frontsector; - -#ifdef ESLOPE - if (slope) - fixedheight = P_GetZAt(slope, psector->soundorg.x, psector->soundorg.y); -#endif - - if (psector->ffloors) - { - ffloor_t *caster = psector->lightlist[R_GetPlaneLight(psector, fixedheight, false)].caster; - psector = caster ? §ors[caster->secnum] : psector; - - if (caster) - { - lightlevel = psector->lightlevel; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = LightLevelToLum(lightlevel); - } - } - if (psector->extra_colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel,psector->extra_colormap->rgba,psector->extra_colormap->fadergba, false, true); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel,NORMALFOG,FADEFOG, false, true); - } - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel,NORMALFOG,FADEFOG, false, true); - -#endif // NOPE - - if (planecolormap) - { - if (fogplane) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, true, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); - } - else - { - if (fogplane) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, true, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); - } + HWR_Lighting(&Surf, lightlevel, planecolormap); if (PolyFlags & (PF_Translucent|PF_Fog)) { - Surf.FlatColor.s.alpha = (UINT8)alpha; - PolyFlags |= PF_Modulated|PF_Clip; + Surf.PolyColor.s.alpha = (UINT8)alpha; + PolyFlags |= PF_Modulated; } else - PolyFlags |= PF_Masked|PF_Modulated|PF_Clip; + PolyFlags |= PF_Masked|PF_Modulated; + + if (PolyFlags & PF_Fog) + HWD.pfnSetShader(6); // fog shader + else if (PolyFlags & PF_Ripple) + HWD.pfnSetShader(5); // water shader + else + HWD.pfnSetShader(1); // floor shader HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags); - -#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->sow = 0.0f; - v3d->tow = 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) { - FOutVector trVerts[4], *wv; - wallVert3D wallVerts[4]; - wallVert3D *pwallVerts; + FOutVector wallVerts[4]; wallsplat_t *splat; GLPatch_t *gpatch; fixed_t i; - FSurfaceInfo pSurf2; // seg bbox fixed_t segbbox[4]; @@ -893,186 +522,69 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) wallVerts[3].s = wallVerts[3].t = wallVerts[2].s = wallVerts[0].t = 0.0f; wallVerts[1].s = wallVerts[1].t = wallVerts[2].t = wallVerts[0].s = 1.0f; - // transform - wv = trVerts; - pwallVerts = wallVerts; - for (i = 0; i < 4; i++,wv++,pwallVerts++) - { - wv->x = pwallVerts->x; - wv->z = pwallVerts->z; - wv->y = pwallVerts->y; - - // Kalaron: TOW and SOW needed to be switched - wv->sow = pwallVerts->t; - wv->tow = pwallVerts->s; - } - M_Memcpy(&pSurf2,pSurf,sizeof (FSurfaceInfo)); switch (splat->flags & SPLATDRAWMODE_MASK) { case SPLATDRAWMODE_OPAQUE : - pSurf2.FlatColor.s.alpha = 0xff; + pSurf.PolyColor.s.alpha = 0xff; i = PF_Translucent; break; case SPLATDRAWMODE_TRANS : - pSurf2.FlatColor.s.alpha = 128; + pSurf.PolyColor.s.alpha = 128; i = PF_Translucent; break; case SPLATDRAWMODE_SHADE : - pSurf2.FlatColor.s.alpha = 0xff; + pSurf.PolyColor.s.alpha = 0xff; i = PF_Substractive; break; } - HWD.pfnDrawPolygon(&pSurf2, trVerts, 4, i|PF_Modulated|PF_Clip|PF_Decal); + HWD.pfnSetShader(2); // wall shader + HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal); } } #endif -// ========================================================================== -// WALL GENERATION FROM SUBSECTOR SEGS -// ========================================================================== - - FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) { switch (transtablenum) { - case tr_trans10 : pSurf->FlatColor.s.alpha = 0xe6;return PF_Translucent; - case tr_trans20 : pSurf->FlatColor.s.alpha = 0xcc;return PF_Translucent; - case tr_trans30 : pSurf->FlatColor.s.alpha = 0xb3;return PF_Translucent; - case tr_trans40 : pSurf->FlatColor.s.alpha = 0x99;return PF_Translucent; - case tr_trans50 : pSurf->FlatColor.s.alpha = 0x80;return PF_Translucent; - case tr_trans60 : pSurf->FlatColor.s.alpha = 0x66;return PF_Translucent; - case tr_trans70 : pSurf->FlatColor.s.alpha = 0x4c;return PF_Translucent; - case tr_trans80 : pSurf->FlatColor.s.alpha = 0x33;return PF_Translucent; - case tr_trans90 : pSurf->FlatColor.s.alpha = 0x19;return PF_Translucent; + 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; + case tr_trans40 : pSurf->PolyColor.s.alpha = 0x99;return PF_Translucent; + case tr_trans50 : pSurf->PolyColor.s.alpha = 0x80;return PF_Translucent; + case tr_trans60 : pSurf->PolyColor.s.alpha = 0x66;return PF_Translucent; + 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; } return PF_Translucent; } -// v1,v2 : the start & end vertices along the original wall segment, that may have been -// clipped so that only a visible portion of the wall seg is drawn. -// floorheight, ceilingheight : depend on wall upper/lower/middle, comes from the sectors. +// ========================================================================== +// Wall generation from subsector segs +// ========================================================================== -static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo * pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); - -// -----------------+ -// HWR_ProjectWall : -// -----------------+ -/* - wallVerts order is : - 3--2 - | /| - |/ | - 0--1 -*/ -static void HWR_ProjectWall(wallVert3D * wallVerts, - FSurfaceInfo * pSurf, - FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) +// +// HWR_ProjectWall +// +void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { - FOutVector trVerts[4]; - FOutVector *wv; + HWR_Lighting(pSurf, lightlevel, wallcolormap); - // transform - wv = trVerts; - // it sounds really stupid to do this conversion with the new T&L code - // we should directly put the right information in the right structure - // wallVerts3D seems ok, doesn't need FOutVector - // also remove the light copy - - // More messy to unwrap, but it's also quicker, uses less memory. - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - - if (wallcolormap) - { - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, false, false); - } - else - { - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); - } - - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blendmode|PF_Modulated|PF_Occlude|PF_Clip); + HWD.pfnSetShader(2); // wall shader + HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude); #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); #endif -#ifdef ALAM_LIGHTING - //Hurdler: TDOD: do static lighting using gr_curline->lm - HWR_WallLighting(trVerts); - - //Hurdler: for better dynamic light in dark area, we should draw the light first - // and then the wall all that with the right blending func - //HWD.pfnDrawPolygon(pSurf, trVerts, 4, PF_Additive|PF_Modulated|PF_Occlude|PF_Clip); -#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 = gr_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 = (gr_viewx - v1x)*v2dy + (v1y - gr_viewy)*v2dx; - - return num / den; -} -#endif - // // HWR_SplitWall // -static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) +void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts @@ -1098,8 +610,8 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, INT32 solid, i; lightlist_t * list = sector->lightlist; - const UINT8 alpha = Surf->FlatColor.s.alpha; - FUINT lightnum = sector->lightlevel; + const UINT8 alpha = Surf->PolyColor.s.alpha; + FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; realtop = top = wallVerts[3].y; @@ -1119,22 +631,21 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, for (i = 0; i < sector->numlights; i++) { #ifdef ESLOPE - if (endtop < endrealbot) + if (endtop < endrealbot) #endif if (top < realbot) return; - // There's a compiler warning here if this comment isn't here because of indentation if (!(list[i].flags & FF_NOSHADE)) { if (pfloor && (pfloor->flags & FF_FOG)) { - lightnum = pfloor->master->frontsector->lightlevel; + lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y); colormap = pfloor->master->frontsector->extra_colormap; } else { - lightnum = *list[i].lightlevel; + lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y); colormap = list[i].extra_colormap; } } @@ -1244,7 +755,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (endbot < endrealbot) endbot = endrealbot; #endif - Surf->FlatColor.s.alpha = alpha; + Surf->PolyColor.s.alpha = alpha; #ifdef ESLOPE wallVerts[3].t = pegt + ((realtop - top) * pegmul); @@ -1287,7 +798,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (top <= realbot) return; - Surf->FlatColor.s.alpha = alpha; + Surf->PolyColor.s.alpha = alpha; #ifdef ESLOPE wallVerts[3].t = pegt + ((realtop - top) * pegmul); @@ -1319,7 +830,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, // HWR_DrawSkyWalls // Draw walls into the depth buffer so that anything behind is culled properly -static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf) +void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) { HWD.pfnSetTexture(NULL); // no texture @@ -1327,26 +838,23 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf) wallVerts[0].t = wallVerts[1].t = 0; wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = 0; - HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL); + + 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 // PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer } // -// HWR_StoreWallRange +// HWR_ProcessSeg // A portion or all of a wall segment will be drawn, from startfrac to endfrac, // where 0 is the start of the segment, 1 the end of the segment // Anything between means the wall segment has been clipped with solidsegs, // reducing wall overdraw to a minimum // -#ifdef NEWCLIP -static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom -#else -static void HWR_StoreWallRange(double startfrac, double endfrac) -#endif +void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { - wallVert3D wallVerts[4]; + FOutVector wallVerts[4]; v2d_t vs, ve; // start, end vertices of 2d line (view from above) fixed_t worldtop, worldbottom; @@ -1369,11 +877,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) extracolormap_t *colormap; FSurfaceInfo Surf; -#ifndef NEWCLIP - if (startfrac > endfrac) - return; -#endif - gr_sidedef = gr_curline->sidedef; gr_linedef = gr_curline->linedef; @@ -1415,35 +918,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) wallVerts[0].z = wallVerts[3].z = vs.y; wallVerts[2].x = wallVerts[1].x = ve.x; wallVerts[2].z = wallVerts[1].z = ve.y; - wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f; + // x offset the texture { - // x offset the texture fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset; - -#ifndef NEWCLIP - // clip texture s start/end coords with solidsegs - if (startfrac > 0.0f && startfrac < 1.0f) - cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac); - else -#endif - cliplow = (float)texturehpeg; - -#ifndef NEWCLIP - if (endfrac > 0.0f && endfrac < 1.0f) - cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac); - else -#endif - cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); + cliplow = (float)texturehpeg; + cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); } - lightnum = gr_frontsector->lightlevel; + lightnum = HWR_CalcWallLight(gr_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = gr_frontsector->extra_colormap; if (gr_frontsector) - { - Surf.FlatColor.s.alpha = 255; - } + Surf.PolyColor.s.alpha = 255; if (gr_backsector) { @@ -1471,11 +958,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { // Both front and back sectors are sky, needs skywall from the frontsector's ceiling, but only if the // backsector is lower - if ((worldhigh <= worldtop) -#ifdef ESLOPE - && (worldhighslope <= worldtopslope) -#endif - ) + 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); @@ -1521,10 +1006,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // 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) -#ifdef ESLOPE - && (worldlowslope >= worldbottomslope) -#endif + 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 @@ -1562,6 +1046,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_DrawSkyWall(wallVerts, &Surf); } + } // hack to allow height changes in outdoor areas @@ -1987,7 +1472,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { if (gr_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn { - Surf.FlatColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode + Surf.PolyColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode blendmode = PF_Masked; } else @@ -2008,21 +1493,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); - - // If there is a colormap change, remove it. -/* if (!(Surf.FlatColor.s.red + Surf.FlatColor.s.green + Surf.FlatColor.s.blue == Surf.FlatColor.s.red/3) - { - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.rgba = 0xffffffff; - }*/ } } 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 != 41) // Ignore horizon line for OGL + if (gr_midtexture && gr_linedef->special != 41) // (Ignore horizon line for OGL) { { fixed_t texturevpeg; @@ -2072,9 +1549,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); #endif - // I don't think that solid walls can use translucent linedef types... + 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 { if (grTex->mipmap.flags & TF_TRANSPARENT) @@ -2134,7 +1612,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) //Hurdler: 3d-floors test -#ifdef R_FAKEFLOORS if (gr_frontsector && gr_backsector && gr_frontsector->tag != gr_backsector->tag && (gr_backsector->ffloors || gr_frontsector->ffloors)) { ffloor_t * rover; @@ -2274,18 +1751,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) blendmode = PF_Fog|PF_NoTexture; - lightnum = 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; - if (rover->master->frontsector->extra_colormap) - { - - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); - } - else - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); - } + 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); @@ -2299,7 +1768,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; - Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } if (gr_frontsector->numlights) @@ -2394,17 +1863,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) blendmode = PF_Fog|PF_NoTexture; - lightnum = 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; - if (rover->master->frontsector->extra_colormap) - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); - } - else - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); - } + 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); @@ -2418,7 +1880,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; - Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } if (gr_backsector->numlights) @@ -2434,19 +1896,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } } } -#endif //Hurdler: end of 3d-floors test } // From PrBoom: // -// e6y: Check whether the player can look beyond this line +// e6y: Check whether the player can look beyond this line, rturns true if we can't // -#ifdef NEWCLIP -static boolean checkforemptylines = true; + +boolean checkforemptylines = true; // Don't modify anything here, just check // Kalaron: Modified for sloped linedefs -static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector) +static boolean CheckClip(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 @@ -2483,34 +1944,45 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks backc1 = backc2 = abacksector->ceilingheight; } - if (viewsector != abacksector && viewsector != afrontsector) + + // 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) { - boolean mydoorclosed = false; // My door? Closed!? (doorclosed is actually otherwise unused in openGL) + checkforemptylines = false; + return true; + } - // If the sector behind the line blocks all kinds of view past it - // (back ceiling is lower than close floor, or back floor is higher than close ceiling) - if ((backc1 <= frontf1 && backc2 <= frontf2) - || (backf1 >= frontc1 && backf2 >= frontc2)) - { - 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; + } - // The door is closed if: - // backsector is 0 height or less and - // back ceiling is higher than close ceiling or we need to render a top texture and - // back floor is lower than close floor or we need to render a bottom texture and - // neither front or back sectors are using the sky ceiling - mydoorclosed = (backc1 <= backf1 && backc2 <= backf2 - && ((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture) - && ((backf1 <= frontf1 && backf2 >= frontf2) || seg->sidedef->bottomtexture) - && (abacksector->ceilingpic != skyflatnum || afrontsector->ceilingpic != skyflatnum)); + // 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 (mydoorclosed) - { - checkforemptylines = false; - return true; - } + 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) + return false; + + if (backf1 > frontf1 || backf2 > frontf2) + return false; + + return true; } // Window. @@ -2526,306 +1998,12 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks // 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 -// hw_newend is one past the last valid seg -static cliprange_t * hw_newend; -static cliprange_t gr_solidsegs[MAXSEGS]; - - -static void printsolidsegs(void) -{ - cliprange_t * start; - if (!hw_newend || cv_grbeta.value != 2) - return; - for (start = gr_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 = gr_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_grclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first, last); - poorhack = true; - } - else - { - highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_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_grclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first,last); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2); - highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_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_grclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first,last); - poorhack = true; - } - else - HWR_StoreWallRange(0, 1); - } - else - { - // There is a fragment after *next. - if (!cv_grclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first,last); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_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 = gr_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_grclipwalls.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 *)gr_curline->pv1, - (polyvertex_t *)gr_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_grclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(0, 1); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2); - highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2); - HWR_StoreWallRange(lowfrac, highfrac); - } - start++; - - if (last <= start->last) - return; - } - - if (first == start->first+1) // 1 line texture - { - if (!cv_grclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(0, 1); - poorhack = true; - } - else - HWR_StoreWallRange(0, 1); - } - else - { - // There is a fragment after *next. - if (!cv_grclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(0,1); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(max(start->last - 1, - start->first), (polyvertex_t *)gr_curline->pv1, - (polyvertex_t *)gr_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 = gr_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) -{ - gr_solidsegs[0].first = -0x7fffffff; - gr_solidsegs[0].last = -1; - gr_solidsegs[1].first = vid.width; //viewwidth; - gr_solidsegs[1].last = 0x7fffffff; - hw_newend = gr_solidsegs+2; -} -#endif // NEWCLIP - -// -----------------+ -// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list. -// Notes : gr_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) +// HWR_AddLine +// Clips the given segment and adds any visible pieces to the line list. +void HWR_AddLine(seg_t *line) { angle_t angle1, angle2; -#ifndef NEWCLIP - INT32 x1, x2; - angle_t span, tspan; -#endif // SoM: Backsector needs to be run through R_FakeFlat static sector_t tempsec; @@ -2844,114 +2022,27 @@ static void HWR_AddLine(seg_t * line) v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y); // OPTIMIZE: quickly reject orthogonal back sides. - angle1 = R_PointToAngle(v1x, v1y); - angle2 = R_PointToAngle(v2x, v2y); + angle1 = R_PointToAngleEx(viewx, viewy, v1x, v1y); + angle2 = R_PointToAngleEx(viewx, viewy, 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; - - // backface culling : span is < ANGLE_180 if ang1 > ang2 : the seg is facing - if (span >= ANGLE_180) - return; - - // Global angle needed by segcalc. - //rw_angle1 = angle1; - angle1 -= dup_viewangle; - angle2 -= dup_viewangle; - - tspan = angle1 + gr_clipangle; - if (tspan > 2*gr_clipangle) - { - tspan -= 2*gr_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return; - - angle1 = gr_clipangle; - } - tspan = gr_clipangle - angle2; - if (tspan > 2*gr_clipangle) - { - tspan -= 2*gr_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return; - - angle2 = (angle_t)-(signed)gr_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-gr_viewx; - fy1 = ((polyvertex_t *)(line->pv1))->y-gr_viewy; - fy2 = (fx1 * gr_viewcos + fy1 * gr_viewsin); - if (fy2 < 0) - // the point is back - fx1 = 0; - else - fx1 = gr_windowcenterx + (fx1 * gr_viewsin - fy1 * gr_viewcos) * gr_centerx / fy2; - - fx2 = ((polyvertex_t *)(line->pv2))->x-gr_viewx; - fy2 = ((polyvertex_t *)(line->pv2))->y-gr_viewy; - fy1 = (fx2 * gr_viewcos + fy2 * gr_viewsin); - if (fy1 < 0) - // the point is back - fx2 = vid.width; - else - fx2 = gr_windowcenterx + (fx2 * gr_viewsin - fy2 * gr_viewcos) * gr_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 = gr_viewangletox[angle1]; - x2 = gr_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 gr_backsector = line->backsector; -#ifdef NEWCLIP if (!line->backsector) - { gld_clipper_SafeAddClipRange(angle2, angle1); - } - else - { + else + { gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true); - if (CheckClip(line, gr_frontsector, gr_backsector)) + if (CheckClip(gr_frontsector, gr_backsector)) { gld_clipper_SafeAddClipRange(angle2, angle1); checkforemptylines = false; @@ -2966,98 +2057,6 @@ static void HWR_AddLine(seg_t * line) HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D return; -#else - // Single sided line? - if (!gr_backsector) - goto clipsolid; - - gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true); - -#ifdef ESLOPE - if (gr_frontsector->f_slope || gr_frontsector->c_slope || gr_backsector->f_slope || gr_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, v1x, v1y); \ - end2 = P_GetZAt(slope, v2x, v2y); \ - } else \ - end1 = end2 = normalheight; - - SLOPEPARAMS(gr_frontsector->f_slope, frontf1, frontf2, gr_frontsector->floorheight) - SLOPEPARAMS(gr_frontsector->c_slope, frontc1, frontc2, gr_frontsector->ceilingheight) - SLOPEPARAMS( gr_backsector->f_slope, backf1, backf2, gr_backsector->floorheight) - SLOPEPARAMS( gr_backsector->c_slope, backc1, backc2, gr_backsector->ceilingheight) -#undef SLOPEPARAMS - - if (viewsector != gr_backsector && viewsector != gr_frontsector) - { - // 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) || gr_curline->sidedef->toptexture) - && ((backf1 <= frontf1 && backf2 >= frontf2) || gr_curline->sidedef->bottomtexture) - && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum)) - goto clipsolid; - - // Window. - if (backc1 != frontc1 || backc2 != frontc2 - || backf1 != frontf1 || backf2 != frontf2) - { - goto clippass; - } - } - else -#endif - { - if (viewsector != gr_backsector && viewsector != gr_frontsector) - { - // Closed door. - if (gr_backsector->ceilingheight <= gr_frontsector->floorheight || - gr_backsector->floorheight >= gr_frontsector->ceilingheight) - goto clipsolid; - } - - // Check for automap fix. - if (gr_backsector->ceilingheight <= gr_backsector->floorheight - && ((gr_backsector->ceilingheight >= gr_frontsector->ceilingheight) || gr_curline->sidedef->toptexture) - && ((gr_backsector->floorheight <= gr_backsector->floorheight) || gr_curline->sidedef->bottomtexture) - && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum)) - goto clipsolid; - - // Window. - if (gr_backsector->ceilingheight != gr_frontsector->ceilingheight || - gr_backsector->floorheight != gr_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(gr_curline, gr_frontsector, gr_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 @@ -3067,28 +2066,24 @@ clipsolid: // // modified to use local variables -static boolean HWR_CheckBBox(fixed_t *bspcoord) +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 (dup_viewx <= bspcoord[BOXLEFT]) + if (viewx <= bspcoord[BOXLEFT]) boxpos = 0; - else if (dup_viewx < bspcoord[BOXRIGHT]) + else if (viewx < bspcoord[BOXRIGHT]) boxpos = 1; else boxpos = 2; - if (dup_viewy >= bspcoord[BOXTOP]) + if (viewy >= bspcoord[BOXTOP]) boxpos |= 0; - else if (dup_viewy > bspcoord[BOXBOTTOM]) + else if (viewy > bspcoord[BOXBOTTOM]) boxpos |= 1<<2; else boxpos |= 2<<2; @@ -3101,59 +2096,9 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) px2 = bspcoord[checkcoord[boxpos][2]]; py2 = bspcoord[checkcoord[boxpos][3]]; -#ifdef NEWCLIP - angle1 = R_PointToAngle(px1, py1); - angle2 = R_PointToAngle(px2, py2); + angle1 = R_PointToAngleEx(viewx, viewy, px1, py1); + angle2 = R_PointToAngleEx(viewx, viewy, 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; - - span = angle1 - angle2; - - // Sitting on a line? - if (span >= ANGLE_180) - return true; - - tspan = angle1 + gr_clipangle; - - if (tspan > 2*gr_clipangle) - { - tspan -= 2*gr_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return false; - - angle1 = gr_clipangle; - } - tspan = gr_clipangle - angle2; - if (tspan > 2*gr_clipangle) - { - tspan -= 2*gr_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return false; - - angle2 = (angle_t)-(signed)gr_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 = gr_viewangletox[angle1]; - sx2 = gr_viewangletox[angle2]; - - // Does not cross a pixel. - if (sx1 == sx2) - return false; - - return HWR_ClipToSolidSegs(sx1, sx2 - 1); -#endif } #ifdef POLYOBJECTS @@ -3165,7 +2110,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) // Adds all segs in all polyobjects in the given subsector. // Modified for hardware rendering. // -static inline void HWR_AddPolyObjectSegs(void) +void HWR_AddPolyObjectSegs(void) { size_t i, j; seg_t *gr_fakeline = Z_Calloc(sizeof(seg_t), PU_STATIC, NULL); @@ -3201,9 +2146,7 @@ static inline void HWR_AddPolyObjectSegs(void) } #ifdef POLYOBJECTS_PLANES -static 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_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { float height; //constant y for all points on the convex flat polygon FOutVector *v3d; @@ -3228,7 +2171,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size + if (nrPlaneVerts > INT16_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; @@ -3333,16 +2276,16 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { // Hurdler: add scrolling texture on floor/ceiling - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations + 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 // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { - tempxsow = FLOAT_TO_FIXED(v3d->sow); - tempytow = FLOAT_TO_FIXED(v3d->tow); - v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(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->x = FIXED_TO_FLOAT(polysector->vertices[i]->x); @@ -3350,23 +2293,21 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, v3d->z = FIXED_TO_FLOAT(polysector->vertices[i]->y); } - if (planecolormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); + HWR_Lighting(&Surf, lightlevel, planecolormap); if (blendmode & PF_Translucent) { - Surf.FlatColor.s.alpha = (UINT8)alpha; - blendmode |= PF_Modulated|PF_Occlude|PF_Clip; + Surf.PolyColor.s.alpha = (UINT8)alpha; + blendmode |= PF_Modulated|PF_Occlude; } else - blendmode |= PF_Masked|PF_Modulated|PF_Clip; + blendmode |= PF_Masked|PF_Modulated; + HWD.pfnSetShader(1); // floor shader HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode); } -static void HWR_AddPolyObjectPlanes(void) +void HWR_AddPolyObjectPlanes(void) { size_t i; sector_t *polyobjsector; @@ -3393,11 +2334,11 @@ static void HWR_AddPolyObjectPlanes(void) 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.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + polyobjsector->lightlevel, Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); } else { - HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); + 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); @@ -3415,11 +2356,11 @@ static void HWR_AddPolyObjectPlanes(void) 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.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + polyobjsector->lightlevel, Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); } else { - HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); + HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum, R_NoEncore(polyobjsector, true)); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, polyobjsector, 255, NULL); @@ -3434,9 +2375,8 @@ static void HWR_AddPolyObjectPlanes(void) // HWR_Subsector : Determine floor/ceiling planes. // : Add sprites of things in sector. // : Draw one or more line segments. -// Notes : Sets gr_cursectorlight to the light of the parent sector, to modulate wall textures // -----------------+ -static void HWR_Subsector(size_t num) +void HWR_Subsector(size_t num) { INT16 count; seg_t *line; @@ -3454,11 +2394,6 @@ static 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) @@ -3488,16 +2423,6 @@ static void HWR_Subsector(size_t num) floorcolormap = ceilingcolormap = gr_frontsector->extra_colormap; - // ------------------------------------------------------------------------ - // 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; - //gr_cursectorlight.red = light; - //gr_cursectorlight.green = light; - //gr_cursectorlight.blue = light; - //gr_cursectorlight.alpha = light; - // ----- for special tricks with HW renderer ----- if (gr_frontsector->pseudoSector) { @@ -3564,59 +2489,39 @@ static void HWR_Subsector(size_t num) sub->sector->extra_colormap = gr_frontsector->extra_colormap; // render floor ? -#ifdef DOPLANES // yeah, easy backface cull! :) - if (cullFloorHeight < dup_viewz) + if (cullFloorHeight < viewz) { if (gr_frontsector->floorpic != skyflatnum) { if (sub->validcount != validcount) { - HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum); - HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false, + HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum, R_NoEncore(gr_frontsector, false)); + HWR_RenderPlane(&extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, floorcolormap); } } - else - { -#ifdef POLYSKY - HWR_RenderSkyPlane(&extrasubsectors[num], locFloorHeight); -#endif - } } - if (cullCeilingHeight > dup_viewz) + if (cullCeilingHeight > viewz) { if (gr_frontsector->ceilingpic != skyflatnum) { if (sub->validcount != validcount) { - HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum); - HWR_RenderPlane(NULL, &extrasubsectors[num], true, + HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum, R_NoEncore(gr_frontsector, true)); + HWR_RenderPlane(&extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, ceilingcolormap); } } - else - { -#ifdef POLYSKY - HWR_RenderSkyPlane(&extrasubsectors[num], locCeilingHeight); -#endif - } } -#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 (gr_frontsector->ceilingpic == skyflatnum || gr_frontsector->floorpic == skyflatnum) - drawsky = true; -#endif - -#ifdef R_FAKEFLOORS if (gr_frontsector->ffloors) { /// \todo fix light, xoffs, yoffs, extracolormap ? @@ -3644,19 +2549,16 @@ static void HWR_Subsector(size_t num) if (centerHeight <= locCeilingHeight && centerHeight >= locFloorHeight && - ((dup_viewz < cullHeight && !(rover->flags & FF_INVERTPLANES)) || - (dup_viewz > cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) + ((viewz < cullHeight && !(rover->flags & FF_INVERTPLANES)) || + (viewz > cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); - else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], @@ -3668,29 +2570,21 @@ static void HWR_Subsector(size_t num) } else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient { - light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); -#ifndef SORTING - HWR_Add3DWater(levelflats[*rover->bottompic].lumpnum, - &extrasubsectors[num], - *rover->bottomheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1, rover->master->frontsector); -#else + light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum, &extrasubsectors[num], false, *rover->bottomheight, *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, + 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); -#endif } else { - HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); - light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, - rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); + 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); } } @@ -3707,19 +2601,16 @@ static void HWR_Subsector(size_t num) if (centerHeight >= locFloorHeight && centerHeight <= locCeilingHeight && - ((dup_viewz > cullHeight && !(rover->flags & FF_INVERTPLANES)) || - (dup_viewz < cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) + ((viewz > cullHeight && !(rover->flags & FF_INVERTPLANES)) || + (viewz < cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); - else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], @@ -3731,36 +2622,25 @@ static void HWR_Subsector(size_t num) } else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { - light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); -#ifndef SORTING - HWR_Add3DWater(levelflats[*rover->toppic].lumpnum, - &extrasubsectors[num], - *rover->topheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1, rover->master->frontsector); -#else + light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum, &extrasubsectors[num], true, *rover->topheight, *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, + 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); -#endif - } else { - HWR_GetFlat(levelflats[*rover->toppic].lumpnum); - light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, - rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); + 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); } } } } -#endif -#endif //doplanes #ifdef POLYOBJECTS // Draw all the polyobjects in this subsector @@ -3829,59 +2709,8 @@ static void HWR_Subsector(size_t num) // traversing subtree recursively. // Just call with BSP root. -#ifdef coolhack -//t;b;l;r -static fixed_t hackbbox[4]; -//BOXTOP, -//BOXBOTTOM, -//BOXLEFT, -//BOXRIGHT -static boolean HWR_CheckHackBBox(fixed_t *bb) +void HWR_RenderBSPNode(INT32 bspnum) { - 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 @@ -3890,129 +2719,20 @@ static void HWR_RenderBSPNode(INT32 bspnum) // Found a subsector? if (bspnum & NF_SUBSECTOR) { - if (bspnum == -1) - { - //*(gr_drawsubsector_p++) = 0; - HWR_Subsector(0); - } - else - { - //*(gr_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR); + if (bspnum != -1) HWR_Subsector(bspnum&(~NF_SUBSECTOR)); - } return; } // Decide which side the view point is on. - side = R_PointOnSide(dup_viewx, dup_viewy, bsp); - - // BP: big hack for a test in lighning ref : 1249753487AB - hwbbox = bsp->bbox[side]; + side = R_PointOnSide(viewx, viewy, bsp); // 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) -{ - gr_drawsubsector_p = gr_drawsubsectors; -} - -// -// Draw subsectors pushed on the drawsubsectors 'stack', back to front -// -static void HWR_RenderSubsectors(void) -{ - while (gr_drawsubsector_p > gr_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; - } - gr_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 (gr_viewangletox[i]>x) - i++; - gr_xtoviewangle[x] = (i<flip) { - swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s; - swallVerts[2].sow = swallVerts[1].sow = 0; + swallVerts[0].s = swallVerts[3].s = gpatch->max_s; + swallVerts[2].s = swallVerts[1].s = 0; } else { - swallVerts[0].sow = swallVerts[3].sow = 0; - swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s; + swallVerts[0].s = swallVerts[3].s = 0; + swallVerts[2].s = swallVerts[1].s = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t; - swallVerts[0].tow = swallVerts[1].tow = 0; + swallVerts[3].t = swallVerts[2].t = gpatch->max_t; + swallVerts[0].t = swallVerts[1].t = 0; } else { - swallVerts[3].tow = swallVerts[2].tow = 0; - swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t; + swallVerts[3].t = swallVerts[2].t = 0; + swallVerts[0].t = swallVerts[1].t = gpatch->max_t; } - sSurf.FlatColor.s.red = 0x00; - sSurf.FlatColor.s.blue = 0x00; - sSurf.FlatColor.s.green = 0x00; - - /*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW) - { - sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel = 255; - extracolormap_t *colormap = sector->extra_colormap; - - if (sector->numlights) - { - INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false); - - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = *sector->lightlist[light].lightlevel; - - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } - else - { - lightlevel = sector->lightlevel; - - if (sector->extra_colormap) - colormap = sector->extra_colormap; - } - - if (colormap) - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true); - else - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true); - }*/ + sSurf.PolyColor.s.red = 0x00; + sSurf.PolyColor.s.blue = 0x00; + sSurf.PolyColor.s.green = 0x00; // shadow is always half as translucent as the sprite itself if (!cv_translucency.value) // use default translucency (main sprite won't have any translucency) - sSurf.FlatColor.s.alpha = 0x80; // default + sSurf.PolyColor.s.alpha = 0x80; // default else if (spr->mobj->flags2 & MF2_SHADOW) - sSurf.FlatColor.s.alpha = 0x20; + sSurf.PolyColor.s.alpha = 0x20; else if (spr->mobj->frame & FF_TRANSMASK) { HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf); - sSurf.FlatColor.s.alpha /= 2; //cut alpha in half! + sSurf.PolyColor.s.alpha /= 2; //cut alpha in half! } else - sSurf.FlatColor.s.alpha = 0x80; // default + sSurf.PolyColor.s.alpha = 0x80; // default - if (sSurf.FlatColor.s.alpha > floorheight/4) + if (sSurf.PolyColor.s.alpha > floorheight/4) { - sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4); - HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); + sSurf.PolyColor.s.alpha = (UINT8)(sSurf.PolyColor.s.alpha - floorheight/4); + HWD.pfnSetShader(1); // floor shader + HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated); } } // This is expecting a pointer to an array containing 4 wallVerts for a sprite static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) { - if (cv_grspritebillboarding.value - && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) - && wallVerts) + if (cv_grspritebillboarding.value && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) && wallVerts) { float basey = FIXED_TO_FLOAT(spr->mobj->z); float lowy = wallVerts[0].y; @@ -4384,10 +3073,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (cv_shadow.value // Shadows enabled && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. -#ifdef ALAM_LIGHTING - && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. - && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. -#endif && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. { //////////////////// @@ -4414,44 +3099,46 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (spr->flip) { - baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s; - baseWallVerts[2].sow = baseWallVerts[1].sow = 0; + baseWallVerts[0].s = baseWallVerts[3].s = gpatch->max_s; + baseWallVerts[2].s = baseWallVerts[1].s = 0; } else { - baseWallVerts[0].sow = baseWallVerts[3].sow = 0; - baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s; + baseWallVerts[0].s = baseWallVerts[3].s = 0; + baseWallVerts[2].s = baseWallVerts[1].s = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t; - baseWallVerts[0].tow = baseWallVerts[1].tow = 0; + baseWallVerts[3].t = baseWallVerts[2].t = gpatch->max_t; + baseWallVerts[0].t = baseWallVerts[1].t = 0; } else { - baseWallVerts[3].tow = baseWallVerts[2].tow = 0; - baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t; - } - - // 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); - 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; + baseWallVerts[3].t = baseWallVerts[2].t = 0; + 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; + } + } + realtop = top = baseWallVerts[3].y; realbot = bot = baseWallVerts[0].y; - towtop = baseWallVerts[3].tow; - towbot = baseWallVerts[0].tow; + towtop = baseWallVerts[3].t; + towbot = baseWallVerts[0].t; towmult = (towbot - towtop) / (top - bot); #ifdef ESLOPE @@ -4466,12 +3153,12 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (!cv_translucency.value) // translucency disabled { - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } else if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4482,11 +3169,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) // work properly under glide nor with fogcolor to ffffff :( // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - alpha = Surf.FlatColor.s.alpha; + alpha = Surf.PolyColor.s.alpha; // Start with the lightlevel and colormap from the top of the sprite lightlevel = *list[sector->numlights - 1].lightlevel; @@ -4581,10 +3268,10 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) #endif #ifdef ESLOPE - wallVerts[3].tow = towtop + ((realtop - top) * towmult); - wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); - wallVerts[0].tow = towtop + ((realtop - bot) * towmult); - wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + 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].y = top; wallVerts[2].y = endtop; @@ -4592,8 +3279,7 @@ 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_grspritebillboarding.value && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) { // Get the x and z of the vertices so billboarding draws correctly realheight = realbot - realtop; @@ -4615,15 +3301,14 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; } #else - wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); - wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); + 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)) + 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; @@ -4641,14 +3326,12 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) } #endif - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); - Surf.FlatColor.s.alpha = alpha; + Surf.PolyColor.s.alpha = alpha; - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWD.pfnSetShader(3); // sprite shader + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); top = bot; #ifdef ESLOPE @@ -4666,31 +3349,29 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) // If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite #ifdef ESLOPE - wallVerts[3].tow = towtop + ((realtop - top) * towmult); - wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); - wallVerts[0].tow = towtop + ((realtop - bot) * towmult); - wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + 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].y = top; wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; #else - wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); - wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); + 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 - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); - Surf.FlatColor.s.alpha = alpha; + Surf.PolyColor.s.alpha = alpha; - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWD.pfnSetShader(3); // sprite shader + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); } // -----------------+ @@ -4705,7 +3386,6 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) 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) @@ -4731,12 +3411,6 @@ static void HWR_DrawSprite(gr_vissprite_t *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 // // 3--2 @@ -4760,21 +3434,21 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (spr->flip) { - wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s; - wallVerts[2].sow = wallVerts[1].sow = 0; + wallVerts[0].s = wallVerts[3].s = gpatch->max_s; + wallVerts[2].s = wallVerts[1].s = 0; }else{ - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + wallVerts[0].s = wallVerts[3].s = 0; + wallVerts[2].s = wallVerts[1].s = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t; - wallVerts[0].tow = wallVerts[1].tow = 0; + wallVerts[3].t = wallVerts[2].t = gpatch->max_t; + wallVerts[0].t = wallVerts[1].t = 0; }else{ - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + wallVerts[3].t = wallVerts[2].t = 0; + wallVerts[0].t = wallVerts[1].t = gpatch->max_t; } // cache the patch in the graphics card memory @@ -4786,10 +3460,6 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (cv_shadow.value // Shadows enabled && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. -#ifdef ALAM_LIGHTING - && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. - && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. -#endif && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. { //////////////////// @@ -4798,19 +3468,23 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) HWR_DrawSpriteShadow(spr, gpatch, this_scale); } - // 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); - 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; - wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co; - } - // 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; + } + } + // This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black. // sprite lighting by modulating the RGB components /// \todo coloured @@ -4824,22 +3498,19 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = sector->lightlevel; - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); } { FBITFIELD blend = 0; if (!cv_translucency.value) // translucency disabled { - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } else if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4850,15 +3521,15 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // work properly under glide nor with fogcolor to ffffff :( // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWD.pfnSetShader(3); // sprite shader + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); } } -#ifdef HWPRECIP // Sprite drawer for precipitation static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) { @@ -4895,11 +3566,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // Let dispoffset work first since this adjust each vertex HWR_RotateSpritePolyToAim(spr, wallVerts); - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + wallVerts[0].s = wallVerts[3].s = 0; + wallVerts[2].s = wallVerts[1].s = gpatch->max_s; - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + wallVerts[3].t = wallVerts[2].t = 0; + wallVerts[0].t = wallVerts[1].t = gpatch->max_t; // cache the patch in the graphics card memory //12/12/99: Hurdler: same comment as above (for md2) @@ -4933,15 +3604,12 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) colormap = sector->extra_colormap; } - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); } if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4952,121 +3620,66 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // work properly under glide nor with fogcolor to ffffff :( // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWD.pfnSetShader(3); // sprite shader + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); } -#endif // -------------------------------------------------------------------------- // Sort vissprites by distance // -------------------------------------------------------------------------- -static gr_vissprite_t gr_vsprsortedhead; + +gr_vissprite_t* gr_vsprorder[MAXVISSPRITES]; + +// 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; + int idiff; + float fdiff; + + // make transparent sprites last + // "boolean to int" + + int transparency1 = (spr1->mobj->flags2 & MF2_SHADOW) || (spr1->mobj->frame & FF_TRANSMASK); + int transparency2 = (spr2->mobj->flags2 & MF2_SHADOW) || (spr2->mobj->frame & FF_TRANSMASK); + idiff = transparency1 - transparency2; + if (idiff != 0) return idiff; + + fdiff = spr2->tz - spr1->tz;// 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. + else if (fdiff > 0) + return 1; + else + return -1; +} + static void HWR_SortVisSprites(void) { UINT32 i; - gr_vissprite_t *ds, *dsprev, *dsnext, *dsfirst; - gr_vissprite_t *best = NULL; - gr_vissprite_t unsorted; - float bestdist = 0.0f; - INT32 bestdispoffset = 0; - - if (!gr_visspritecount) - return; - - dsfirst = HWR_GetVisSprite(0); - - for (i = 0, dsnext = dsfirst, ds = NULL; i < gr_visspritecount; i++) - { - dsprev = ds; - ds = dsnext; - if (i < gr_visspritecount - 1) dsnext = HWR_GetVisSprite(i + 1); - - ds->next = dsnext; - ds->prev = dsprev; - } - - // 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; - unsorted.prev = ds; - - // pull the vissprites out by scale - gr_vsprsortedhead.next = gr_vsprsortedhead.prev = &gr_vsprsortedhead; for (i = 0; i < gr_visspritecount; i++) { - best = NULL; - for (ds = unsorted.next; ds != &unsorted; ds = ds->next) - { - if (!best || ds->tz > bestdist) - { - bestdist = ds->tz; - bestdispoffset = ds->dispoffset; - best = ds; - } - // order visprites of same scale by dispoffset, smallest first - else if (fabsf(ds->tz - bestdist) < 1.0E-36f && ds->dispoffset < bestdispoffset) - { - bestdispoffset = ds->dispoffset; - best = ds; - } - } - if (best) - { - best->next->prev = best->prev; - best->prev->next = best->next; - best->next = &gr_vsprsortedhead; - best->prev = gr_vsprsortedhead.prev; - } - gr_vsprsortedhead.prev->next = best; - gr_vsprsortedhead.prev = best; - } - - // 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 - best = gr_vsprsortedhead.next; - for (i = 0; i < gr_visspritecount; i++) - { - if ((best->mobj->flags2 & MF2_SHADOW) || (best->mobj->frame & FF_TRANSMASK)) - { - if (best == gr_vsprsortedhead.next) - { - gr_vsprsortedhead.next = best->next; - } - best->prev->next = best->next; - best->next->prev = best->prev; - best->prev = gr_vsprsortedhead.prev; - gr_vsprsortedhead.prev->next = best; - gr_vsprsortedhead.prev = best; - ds = best; - best = best->next; - ds->next = &gr_vsprsortedhead; - } - else - best = best->next; + gr_vsprorder[i] = HWR_GetVisSprite(i); } + qsort(gr_vsprorder, gr_visspritecount, sizeof(gr_vissprite_t*), CompareVisSprites); } // 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 { - wallVert3D wallVerts[4]; + FOutVector wallVerts[4]; FSurfaceInfo Surf; INT32 texnum; FBITFIELD blend; INT32 drawcount; -#ifndef SORTING - fixed_t fixedheight; -#endif boolean fogwall; INT32 lightlevel; extracolormap_t *wallcolormap; // Doing the lighting in HWR_RenderWall now for correct fog after sorting @@ -5075,10 +3688,6 @@ typedef struct static wallinfo_t *wallinfo = NULL; static size_t numwalls = 0; // a list of transparent walls to be drawn -static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); - -#define MAX_TRANSPARENTWALL 256 - typedef struct { extrasubsector_t *xsub; @@ -5114,30 +3723,19 @@ typedef struct static size_t numpolyplanes = 0; // a list of transparent poyobject floors to be drawn static polyplaneinfo_t *polyplaneinfo = NULL; -#ifndef SORTING -size_t numfloors = 0; -#else -//static floorinfo_t *floorinfo = NULL; -//static size_t numfloors = 0; -//Hurdler: 3D water sutffs typedef struct gr_drawnode_s { planeinfo_t *plane; polyplaneinfo_t *polyplane; wallinfo_t *wall; gr_vissprite_t *sprite; - -// struct gr_drawnode_s *next; -// struct gr_drawnode_s *prev; } gr_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(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) { static size_t allocedplanes = 0; @@ -5168,8 +3766,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(lumpnum_t lumpnum, 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; @@ -5196,28 +3793,65 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, numpolyplanes++; } -// -// HWR_CreateDrawNodes -// Creates and sorts a list of drawnodes for the scene being rendered. -static void HWR_CreateDrawNodes(void) +// putting sortindex and sortnode here so the comparator function can see them +gr_drawnode_t *sortnode; +size_t *sortindex; + +static int CompareDrawNodes(const void *p1, const void *p2) { - UINT32 i = 0, p = 0, prev = 0, loop; - const fixed_t pviewz = dup_viewz; + size_t n1 = *(const size_t*)p1; + size_t n2 = *(const size_t*)p2; + INT32 v1 = 0; + INT32 v2 = 0; + INT32 diff; + if (sortnode[n1].plane) + v1 = sortnode[n1].plane->drawcount; + else if (sortnode[n1].polyplane) + v1 = sortnode[n1].polyplane->drawcount; + else if (sortnode[n1].wall) + v1 = sortnode[n1].wall->drawcount; + else I_Error("n1 unknown"); + + if (sortnode[n2].plane) + v2 = sortnode[n2].plane->drawcount; + else if (sortnode[n2].polyplane) + v2 = sortnode[n2].polyplane->drawcount; + else if (sortnode[n2].wall) + v2 = sortnode[n2].wall->drawcount; + else I_Error("n2 unknown"); + + diff = v2 - v1; + if (diff == 0) I_Error("diff is zero"); + return diff; +} + +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)"); + 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) +{ + UINT32 i = 0, p = 0; + size_t run_start = 0; // Dump EVERYTHING into a huge drawnode list. Then we'll sort it! // Could this be optimized into _AddTransparentWall/_AddTransparentPlane? // Hell yes! But sort algorithm must be modified to use a linked list. - gr_drawnode_t *sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes) + sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes) + (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. - size_t *sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL); - - // If true, swap the draw order. - boolean shift = false; + sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL); for (i = 0; i < numplanes; i++, p++) { @@ -5244,102 +3878,45 @@ static void HWR_CreateDrawNodes(void) // through the lists of masked textures and // translucent ffloors being drawn. - // This is a bubble sort! Wahoo! + // 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! + qsort(sortindex, p, sizeof(size_t), CompareDrawNodes); - // Stuff is sorted: - // sortnode[sortindex[0]] = farthest away - // sortnode[sortindex[p-1]] = closest - // "i" should be closer. "prev" should be further. - // The lower drawcount is, the further it is from the screen. - - for (loop = 0; loop < p; loop++) + // try solving floor order here. for each consecutive run of floors in the list, sort that run. + while (run_start < p-1)// p-1 because a 1 plane run at the end of the list does not count { - for (i = 1; i < p; i++) + // locate run start + if (sortnode[sortindex[run_start]].plane) { - prev = i-1; - if (sortnode[sortindex[i]].plane) + // found it, now look for run end + size_t run_end;// (inclusive) + for (i = run_start+1; i < p; i++)// size_t and UINT32 being used mixed here... shouldnt break anything though.. { - // What are we comparing it with? - if (sortnode[sortindex[prev]].plane) - { - // Plane (i) is further away than plane (prev) - if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz)) - shift = true; - } - if (sortnode[sortindex[prev]].polyplane) - { - // Plane (i) is further away than polyplane (prev) - if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz)) - shift = true; - } - else if (sortnode[sortindex[prev]].wall) - { - // Plane (i) is further than wall (prev) - if (sortnode[sortindex[i]].plane->drawcount > sortnode[sortindex[prev]].wall->drawcount) - shift = true; - } + if (!sortnode[sortindex[i]].plane) break; } - else if (sortnode[sortindex[i]].polyplane) + run_end = i-1; + if (run_end > run_start)// if there are multiple consecutive planes, not just one { - // What are we comparing it with? - if (sortnode[sortindex[prev]].plane) - { - // Plane (i) is further away than plane (prev) - if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz)) - shift = true; - } - if (sortnode[sortindex[prev]].polyplane) - { - // Plane (i) is further away than polyplane (prev) - if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz)) - shift = true; - } - else if (sortnode[sortindex[prev]].wall) - { - // Plane (i) is further than wall (prev) - if (sortnode[sortindex[i]].polyplane->drawcount > sortnode[sortindex[prev]].wall->drawcount) - shift = true; - } - } - else if (sortnode[sortindex[i]].wall) - { - // What are we comparing it with? - if (sortnode[sortindex[prev]].plane) - { - // Wall (i) is further than plane(prev) - if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].plane->drawcount) - shift = true; - } - if (sortnode[sortindex[prev]].polyplane) - { - // Wall (i) is further than polyplane(prev) - if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].polyplane->drawcount) - shift = true; - } - else if (sortnode[sortindex[prev]].wall) - { - // Wall (i) is further than wall (prev) - if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].wall->drawcount) - shift = true; - } + // 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 + } + else + { + // this wasnt the run start, try next one + run_start++; + } + } - if (shift) - { - size_t temp; - - temp = sortindex[prev]; - sortindex[prev] = sortindex[i]; - sortindex[i] = temp; - - shift = false; - } - - } //i++ - } // loop++ - - HWD.pfnSetTransform(&atransform); // Okay! Let's draw it all! Woo! + HWD.pfnSetTransform(&atransform); + HWD.pfnSetShader(0); + for (i = 0; i < p; i++) { if (sortnode[sortindex[i]].plane) @@ -5348,9 +3925,9 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) - HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum); - 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->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + 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); } else if (sortnode[sortindex[i]].polyplane) { @@ -5358,7 +3935,7 @@ static void HWR_CreateDrawNodes(void) gr_frontsector = NULL; if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) - HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum); + HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum, 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); } @@ -5380,62 +3957,49 @@ static void HWR_CreateDrawNodes(void) Z_Free(sortindex); } -#endif - // -------------------------------------------------------------------------- // Draw all vissprites // -------------------------------------------------------------------------- -#ifdef SORTING -// 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) +void HWR_DrawSprites(void) { - if (gr_visspritecount > 0) + UINT32 i; + for (i = 0; i < gr_visspritecount; i++) { - gr_vissprite_t *spr; - - // draw all vissprites back to front - for (spr = gr_vsprsortedhead.next; - spr != &gr_vsprsortedhead; - spr = spr->next) - { -#ifdef HWPRECIP - if (spr->precip) - HWR_DrawPrecipitationSprite(spr); - else -#endif - if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - { - // 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))) - HWR_DrawSprite(spr); - else - HWR_DrawMD2(spr); - } + gr_vissprite_t *spr = gr_vsprorder[i]; + if (spr->precip) + HWR_DrawPrecipitationSprite(spr); + else + if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + { + // 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]) + HWR_DrawSprite(spr); else - { - if (!cv_grmdls.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) - HWR_DrawSprite(spr); - else - HWR_DrawMD2(spr); - } - } + HWR_DrawMD2(spr); + } + else + { + if (!cv_grmdls.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + HWR_DrawSprite(spr); + else + HWR_DrawMD2(spr); + } } } -#endif // -------------------------------------------------------------------------- // HWR_AddSprites // During BSP traversal, this adds sprites by sector. // -------------------------------------------------------------------------- -static UINT8 sectorlight; -static void HWR_AddSprites(sector_t *sec) +void HWR_AddSprites(sector_t *sec) { mobj_t *thing; -#ifdef HWPRECIP precipmobj_t *precipthing; -#endif fixed_t approx_dist, limit_dist; + INT32 splitflags; + boolean split_drawsprite; // drawing with splitscreen flags + // BSP is traversed by subsector. // A sector might have been split into several // subsectors during BSP building. @@ -5446,36 +4010,43 @@ static 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)(/*(maptol & TOL_NIGHTS) ? cv_drawdist_nights.value : */cv_drawdist.value) << FRACBITS)) { for (thing = sec->thinglist; thing; thing = thing->snext) { + + split_drawsprite = false; + if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) continue; - if (splitscreen) + splitflags = thing->eflags & (MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); + + if (splitscreen && splitflags) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (viewssnum != 0) - continue; + if (viewssnum == 0) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP2) - if (viewssnum != 1) - continue; + if (viewssnum == 1) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (viewssnum != 2) - continue; + if (viewssnum == 2) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (viewssnum != 3) - continue; + if (viewssnum == 3) + split_drawsprite = true; } + else + split_drawsprite = true; + + if (!split_drawsprite) + continue; approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); @@ -5490,33 +4061,42 @@ static void HWR_AddSprites(sector_t *sec) // Draw everything in sector, no checks for (thing = sec->thinglist; thing; thing = thing->snext) { + + split_drawsprite = false; + if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) continue; - if (splitscreen) + splitflags = thing->eflags & (MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); + + if (splitscreen && splitflags) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (viewssnum != 0) - continue; + if (viewssnum == 0) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP2) - if (viewssnum != 1) - continue; + if (viewssnum == 1) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (viewssnum != 2) - continue; + if (viewssnum == 2) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (viewssnum != 3) - continue; + if (viewssnum == 3) + split_drawsprite = true; } + else + split_drawsprite = true; + + if (!split_drawsprite) + continue; HWR_ProjectSprite(thing); } } -#ifdef HWPRECIP // No to infinite precipitation draw distance. if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) { @@ -5533,7 +4113,6 @@ static void HWR_AddSprites(sector_t *sec) HWR_ProjectPrecipitationSprite(precipthing); } } -#endif } // -------------------------------------------------------------------------- @@ -5541,12 +4120,13 @@ static 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 ?.... -static void HWR_ProjectSprite(mobj_t *thing) +void HWR_ProjectSprite(mobj_t *thing) { gr_vissprite_t *vis; float tr_x, tr_y; float tz; float x1, x2; + float z1, z2; float rightsin, rightcos; float this_scale; float gz, gzt; @@ -5556,9 +4136,8 @@ static void HWR_ProjectSprite(mobj_t *thing) unsigned rot; UINT8 flip; angle_t ang; - INT32 heightsec, phs; const boolean papersprite = (thing->frame & FF_PAPERSPRITE); - float z1, z2; + INT32 heightsec, phs; if (!thing) return; @@ -5686,6 +4265,7 @@ static void HWR_ProjectSprite(mobj_t *thing) x1 = tr_x + x1 * rightcos; x2 = tr_x - x2 * rightcos; + if (thing->eflags & MFE_VERTICALFLIP) { gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale; @@ -5732,8 +4312,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->patchlumpnum = sprframe->lumppat[rot]; 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" @@ -5762,7 +4341,7 @@ static void HWR_ProjectSprite(mobj_t *thing) { vis->colormap = colormaps; #ifdef GLENCORE - if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK))) + if (encoremap && (thing->flags & (MF_SCENERY|MF_NOTHINK)) && !(thing->flags & MF_DONTENCOREMAP)) vis->colormap += (256*32); #endif } @@ -5781,9 +4360,8 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->precip = false; } -#ifdef HWPRECIP // Precipitation projector for hardware mode -static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) +void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) { gr_vissprite_t *vis; float tr_x, tr_y; @@ -5879,8 +4457,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->mobj = (mobj_t *)thing; vis->colormap = colormaps; + #ifdef GLENCORE - if (encoremap) + if (encoremap && !(thing->flags & MF_DONTENCOREMAP)) vis->colormap += (256*32); #endif @@ -5889,96 +4468,40 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->precip = true; } -#endif -// ========================================================================== -// -// ========================================================================== -static void HWR_DrawSkyBackground(void) +static boolean drewsky = false; + +void HWR_DrawSkyBackground(float fpov) { - FOutVector v[4]; - angle_t angle; - float dimensionmultiply; - float aspectratio; - float angleturn; + FTransform dometransform; + + if (drewsky) + return; + + memset(&dometransform, 0x00, sizeof(FTransform)); + + //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); + + dometransform.flip = atransform.flip; + dometransform.mirror = atransform.mirror; + dometransform.shearing = atransform.shearing; + dometransform.viewaiming = atransform.viewaiming; + + dometransform.scalex = 1; + dometransform.scaley = (float)vid.width/vid.height; + dometransform.scalez = 1; + dometransform.fovxangle = fpov; // Tails + dometransform.fovyangle = fpov; // Tails + dometransform.splitscreen = splitscreen; 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 + gr_xtoviewangle[0]); - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - - if (atransform.mirror) - { - angle = InvAngle(angle); - dimensionmultiply *= -1; - } - - v[0].sow = v[3].sow = ((float) angle / ((ANGLE_90-1)*dimensionmultiply)); - v[2].sow = v[1].sow = (-1.0f/dimensionmultiply)+((float) angle / ((ANGLE_90-1)*dimensionmultiply)); - - // Y - angle = aimingangle; - - dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); - - if (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].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); - v[0].tow = v[1].tow = (-1.0f/dimensionmultiply)-(0.5f-(0.5f/dimensionmultiply)); - } - else - { - v[3].tow = v[2].tow = (-1.0f/dimensionmultiply)-(0.5f-(0.5f/dimensionmultiply)); - v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); - } - - 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].tow = v[2].tow += ((float) angle / angleturn); - v[0].tow = v[1].tow += ((float) angle / angleturn); - } - else - { - v[3].tow = v[2].tow -= ((float) angle / angleturn); - v[0].tow = v[1].tow -= ((float) angle / angleturn); - } - - HWD.pfnDrawPolygon(NULL, v, 4, 0); + HWD.pfnSetShader(7); // sky shader + HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, dometransform); + HWD.pfnSetShader(0); } @@ -5987,23 +4510,12 @@ static void HWR_DrawSkyBackground(void) // -----------------+ static inline void HWR_ClearView(void) { - // 3--2 - // | /| - // |/ | - // 0--1 - - /// \bug faB - enable depth mask, disable color mask - HWD.pfnGClipRect((INT32)gr_viewwindowx, (INT32)gr_viewwindowy, (INT32)(gr_viewwindowx + gr_viewwidth), (INT32)(gr_viewwindowy + gr_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); } @@ -6037,35 +4549,16 @@ void HWR_SetViewSize(void) HWD.pfnFlushScreenTextures(); } + // ========================================================================== -// Same as rendering the player view, but from the skybox object +// Render the current frame. // ========================================================================== -void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) +void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox) { + angle_t a1; const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); - postimg_t *type; - - type = &postimgtype[viewnumber]; - - { - // 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(viewnumber); -#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; + postimg_t *postprocessor = &postimgtype[0]; + INT32 i; // set window position gr_centerx = gr_basecenterx; @@ -6090,163 +4583,115 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) // check for new console commands. NetUpdate(); - gr_viewx = FIXED_TO_FLOAT(dup_viewx); - gr_viewy = FIXED_TO_FLOAT(dup_viewy); - gr_viewz = FIXED_TO_FLOAT(dup_viewz); + 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); - gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(aimingangle>>ANGLETOFINESHIFT)); - gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(aimingangle>>ANGLETOFINESHIFT)); + // 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 gr_viewxxx when finished - atransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - atransform.anglez = 0.0f; - - if (*type == postimg_flip) - atransform.flip = true; - else - atransform.flip = false; - - if (*type == postimg_mirror) - atransform.mirror = true; - else - atransform.mirror = false; - - atransform.x = gr_viewx; // FIXED_TO_FLOAT(viewx) - atransform.y = gr_viewy; // FIXED_TO_FLOAT(viewy) - atransform.z = gr_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 atransform.splitscreen = splitscreen; - gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); + for (i = 0; i <= splitscreen; i++) + { + if (player == &players[displayplayers[i]]) + postprocessor = &postimgtype[i]; + } - //------------------------------------------------------------------------ + 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 (0) -{ // I don't think this is ever used. - if (cv_grfog.value) - HWR_FoggingOn(); // First of all, turn it on, set the default user settings too - else - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off -} - - if (drawsky) - HWR_DrawSkyBackground(); - - //Hurdler: it doesn't work in splitscreen mode - drawsky = splitscreen; - HWR_ClearSprites(); -#ifdef SORTING - drawcount = 0; -#endif -#ifdef NEWCLIP - if (rendermode == render_opengl) - { - angle_t a1 = gld_FrustumAngle(); - gld_clipper_Clear(); - gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); + ST_doPaletteStuff(); + + // 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 HAVE_SPHEREFRUSTRUM - gld_FrustrumSetup(); -#endif - } -#else - HWR_ClearClipSegs(); + gld_FrustrumSetup(); #endif - //04/01/2000: Hurdler: added for T&L - // Actually it only works on Walls and Planes + // Set transform. HWD.pfnSetTransform(&atransform); + // Reset the shader state. + HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); + HWD.pfnSetShader(0); + + if (cv_grbatching.value) + HWD.pfnStartBatching(); + + drawcount = 0; validcount++; + // Recursively "render" the BSP tree. HWR_RenderBSPNode((INT32)numnodes-1); -#ifndef NEWCLIP - // Make a viewangle int so we can render things based on mouselook - if (player == &players[consoleplayer]) - viewangle = localaiming[0]; - else if (splitscreen && player == &players[displayplayers[1]]) - viewangle = localaiming[1]; - else if (splitscreen > 1 && player == &players[displayplayers[2]]) - viewangle = localaiming[2]; - else if (splitscreen > 2 && player == &players[displayplayers[3]]) - viewangle = localaiming[3]; - - // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) + if (cv_grbatching.value) { - dup_viewangle += ANGLE_90; - HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //left - - dup_viewangle += ANGLE_90; - if (((INT32)aimingangle > ANGLE_45 || (INT32)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; + 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); } -#endif // 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 + // 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(); // Draw MD2 and sprites -#ifdef SORTING HWR_SortVisSprites(); -#endif - -#ifdef SORTING HWR_DrawSprites(); -#endif -#ifdef NEWCORONAS - //Hurdler: they must be drawn before translucent planes, what about gl fog? - HWR_DrawCoronas(); -#endif -#ifdef SORTING - if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything - { - HWR_CreateDrawNodes(); - } -#else - if (numfloors || numwalls) - { - HWD.pfnSetTransform(&atransform); - if (numfloors) - HWR_Render3DWater(); - if (numwalls) - HWR_RenderTransparentWalls(); - } -#endif + if (numplanes || numpolyplanes || numwalls) // Render FOFs and translucent walls after everything + HWR_RenderDrawNodes(); + // Unset transform and shader HWD.pfnSetTransform(NULL); + HWD.pfnUnSetShader(); - // put it off for menus etc - if (cv_grfog.value) - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); + // Run post processor effects + if (!skybox) + HWR_DoPostProcessor(player); // Check for new console commands. NetUpdate(); @@ -6257,300 +4702,44 @@ if (0) } // ========================================================================== -// +// Render the player view. // ========================================================================== void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) { - const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); - postimg_t *type = &postimgtype[viewnumber]; - const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on - FRGBAFloat ClearColor; - - type = &postimgtype[viewnumber]; - - ClearColor.red = 0.0f; - ClearColor.green = 0.0f; - ClearColor.blue = 0.0f; - ClearColor.alpha = 1.0f; - + // 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 - HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. - - if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox - HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind - { - // 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(viewnumber); -#endif + FRGBAFloat ClearColor; + + ClearColor.red = 0.0f; + ClearColor.green = 0.0f; + ClearColor.blue = 0.0f; + ClearColor.alpha = 1.0f; + + HWD.pfnClearBuffer(true, false, &ClearColor); + } + + if (viewnumber > 3) + return; + + // Render the skybox if there is one. + drewsky = false; + if (skybox) + { + R_SkyboxFrame(player); + HWR_RenderFrame(viewnumber, player, true); } - // note: sets viewangle, viewx, viewy, viewz 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 - - // 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 ((splitscreen == 1 && viewnumber == 1) || (splitscreen > 1 && viewnumber > 1)) - { - gr_viewwindowy += gr_viewheight; - gr_windowcentery += gr_viewheight; - } - - if (splitscreen > 1 && viewnumber & 1) - { - gr_viewwindowx += gr_viewwidth; - gr_windowcenterx += gr_viewwidth; - } - - // check for new console commands. - NetUpdate(); - - gr_viewx = FIXED_TO_FLOAT(dup_viewx); - gr_viewy = FIXED_TO_FLOAT(dup_viewy); - gr_viewz = FIXED_TO_FLOAT(dup_viewz); - gr_viewsin = FIXED_TO_FLOAT(viewsin); - gr_viewcos = FIXED_TO_FLOAT(viewcos); - - gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(aimingangle>>ANGLETOFINESHIFT)); - gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(aimingangle>>ANGLETOFINESHIFT)); - - //04/01/2000: Hurdler: added for T&L - // It should replace all other gr_viewxxx when finished - atransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - atransform.anglez = 0.0f; - - if (*type == postimg_flip) - atransform.flip = true; - else - atransform.flip = false; - - if (*type == postimg_mirror) - atransform.mirror = true; - else - atransform.mirror = false; - - atransform.x = gr_viewx; // FIXED_TO_FLOAT(viewx) - atransform.y = gr_viewy; // FIXED_TO_FLOAT(viewy) - atransform.z = gr_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 - atransform.splitscreen = splitscreen; - - gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); - - //------------------------------------------------------------------------ - HWR_ClearView(); // Clears the depth buffer and resets the view I believe - -if (0) -{ // I don't think this is ever used. - if (cv_grfog.value) - HWR_FoggingOn(); // First of all, turn it on, set the default user settings too - else - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off -} - - if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox - HWR_DrawSkyBackground(); - - //Hurdler: it doesn't work in splitscreen mode - drawsky = splitscreen; - - HWR_ClearSprites(); - -#ifdef SORTING - drawcount = 0; -#endif -#ifdef NEWCLIP - if (rendermode == render_opengl) - { - angle_t a1 = gld_FrustumAngle(); - 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); - - validcount++; - - HWR_RenderBSPNode((INT32)numnodes-1); - -#ifndef NEWCLIP - // Make a viewangle int so we can render things based on mouselook - if (player == &players[consoleplayer]) - viewangle = localaiming[0]; - else if (splitscreen && player == &players[displayplayers[1]]) - viewangle = localaiming[1]; - else if (splitscreen > 1 && player == &players[displayplayers[2]]) - viewangle = localaiming[2]; - else if (splitscreen > 2 && player == &players[displayplayers[3]]) - viewangle = localaiming[3]; - - // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) - { - dup_viewangle += ANGLE_90; - HWR_ClearClipSegs(); - HWR_RenderBSPNode((INT32)numnodes-1); //left - - dup_viewangle += ANGLE_90; - if (((INT32)aimingangle > ANGLE_45 || (INT32)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 - - // 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 -#ifdef SORTING - HWR_SortVisSprites(); -#endif - -#ifdef SORTING - HWR_DrawSprites(); -#endif -#ifdef NEWCORONAS - //Hurdler: they must be drawn before translucent planes, what about gl fog? - HWR_DrawCoronas(); -#endif - -#ifdef SORTING - if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything - { - HWR_CreateDrawNodes(); - } -#else - if (numfloors || numpolyplanes || numwalls) - { - HWD.pfnSetTransform(&atransform); - if (numfloors) - HWR_Render3DWater(); - if (numwalls) - HWR_RenderTransparentWalls(); - } -#endif - - HWD.pfnSetTransform(NULL); - - // put it off for menus etc - if (cv_grfog.value) - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); - - 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); -} - -// ========================================================================== -// FOG -// ========================================================================== - -/// \author faB - -static UINT32 atohex(const char *s) -{ - INT32 iCol; - const char *sCol; - char cCol; - INT32 i; - - if (strlen(s)<6) - return 0; - - iCol = 0; - sCol = s; - for (i = 0; i < 6; i++, sCol++) - { - iCol <<= 4; - cCol = *sCol; - if (cCol >= '0' && cCol <= '9') - iCol |= cCol - '0'; - else - { - if (cCol >= 'F') - cCol -= 'a' - 'A'; - if (cCol >= 'A' && cCol <= 'F') - iCol = iCol | (cCol - 'A' + 10); - } - } - //CONS_Debug(DBG_RENDER, "col %x\n", iCol); - return iCol; -} - -static void HWR_FoggingOn(void) -{ - HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, atohex(cv_grfogcolor.string)); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1); + HWR_RenderFrame(viewnumber, player, false); } // ========================================================================== // 3D ENGINE COMMANDS // ========================================================================== - - -static void Command_GrStats_f(void) -{ - Z_CheckHeap(9875); // debug - - CONS_Printf(M_GetText("Patch info headers: %7s kb\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); - CONS_Printf(M_GetText("3D Texture cache : %7s kb\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); - CONS_Printf(M_GetText("Plane polygon : %7s kb\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); -} - - // ************************************************************************** // 3D ENGINE SETUP // ************************************************************************** @@ -6562,31 +4751,14 @@ static void Command_GrStats_f(void) void HWR_AddCommands(void) { CV_RegisterVar(&cv_grrounddown); - CV_RegisterVar(&cv_grfogdensity); CV_RegisterVar(&cv_grfiltermode); CV_RegisterVar(&cv_granisotropicmode); CV_RegisterVar(&cv_grcorrecttricks); CV_RegisterVar(&cv_grsolvetjoin); + + CV_RegisterVar(&cv_grbatching); } -static inline void HWR_AddEngineCommands(void) -{ - // engine state variables - //CV_RegisterVar(&cv_grzbuffer); -#ifndef NEWCLIP - CV_RegisterVar(&cv_grclipwalls); -#endif - - // engine development mode variables - // - usage may vary from version to version.. - CV_RegisterVar(&cv_gralpha); - CV_RegisterVar(&cv_grbeta); - - // engine commands - COM_AddCommand("gr_stats", Command_GrStats_f); -} - - // -------------------------------------------------------------------------- // Setup the hardware renderer // -------------------------------------------------------------------------- @@ -6594,27 +4766,12 @@ void HWR_Startup(void) { static boolean startupdone = false; - // setup GLPatch_t scaling - gr_patch_scalex = (float)(1.0f / vid.width); - gr_patch_scaley = (float)(1.0f / vid.height); - - // initalze light lut translation - InitLumLut(); - // do this once if (!startupdone) { - CONS_Printf("HWR_Startup()\n"); - HWR_InitPolyPool(); - // add console cmds & vars - HWR_AddEngineCommands(); + CONS_Printf("HWR_Startup()...\n"); HWR_InitTextureCache(); - HWR_InitMD2(); - -#ifdef ALAM_LIGHTING - HWR_InitLight(); -#endif } if (rendermode == render_opengl) @@ -6626,6 +4783,11 @@ void HWR_Startup(void) #endif startupdone = true; + + // jimita + HWD.pfnKillShaders(); + if (!HWD.pfnLoadShaders()) + gr_shadersavailable = false; } @@ -6636,137 +4798,11 @@ 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 - gr_viewx; - tr_y = *cz - gr_viewy; -// *cy = *cy; - - // rotation around vertical y axis - *cx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos); - tr_x = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); - - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_y = *cy - gr_viewz; - - *cy = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - *cz = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - - //scale y before frustum so that frustum can be scaled to screen height - *cy *= ORIGINAL_ASPECT * gr_fovlud; - *cx *= gr_fovlud; -} - - -//Hurdler: 3D Water stuff -#define MAX_3DWATER 512 - -#ifndef SORTING -static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, - fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector) -{ - static size_t allocedplanes = 0; - - // Force realloc if buffer has been freed - if (!planeinfo) - allocedplanes = 0; - - if (allocedplanes < numfloors + 1) - { - allocedplanes += MAX_3DWATER; - Z_Realloc(planeinfo, allocedplanes * sizeof (*planeinfo), PU_LEVEL, &planeinfo); - } - planeinfo[numfloors].fixedheight = fixedheight; - planeinfo[numfloors].lightlevel = lightlevel; - planeinfo[numfloors].lumpnum = lumpnum; - planeinfo[numfloors].xsub = xsub; - planeinfo[numfloors].alpha = alpha; - planeinfo[numfloors].FOFSector = FOFSector; - numfloors++; -} -#endif - -#define DIST_PLANE(i) ABS(planeinfo[(i)].fixedheight-dup_viewz) - -#if 0 -static void HWR_QuickSortPlane(INT32 start, INT32 finish) -{ - INT32 left = start; - INT32 right = finish; - INT32 starterval = (INT32)((right+left)/2); //pick a starter - - planeinfo_t temp; - - //'sort of sort' the two halves of the data list about starterval - while (right > left); - { - while (DIST_PLANE(left) < DIST_PLANE(starterval)) left++; //attempt to find a bigger value on the left - while (DIST_PLANE(right) > DIST_PLANE(starterval)) right--; //attempt to find a smaller value on the right - - if (left < right) //if we haven't gone too far - { - //switch them - M_Memcpy(&temp, &planeinfo[left], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[left], &planeinfo[right], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[right], &temp, sizeof (planeinfo_t)); - //move the bounds - left++; - right--; - } - } - - if (start < right) HWR_QuickSortPlane(start, right); - if (left < finish) HWR_QuickSortPlane(left, finish); -} -#endif - -#ifndef SORTING -static void HWR_Render3DWater(void) -{ - size_t i; - - //bubble sort 3D Water for correct alpha blending - { - boolean permut = true; - while (permut) - { - size_t j; - for (j = 0, permut= false; j < numfloors-1; j++) - { - if (ABS(planeinfo[j].fixedheight-dup_viewz) < ABS(planeinfo[j+1].fixedheight-dup_viewz)) - { - planeinfo_t temp; - M_Memcpy(&temp, &planeinfo[j+1], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[j+1], &planeinfo[j], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[j], &temp, sizeof (planeinfo_t)); - permut = true; - } - } - } - } -#if 0 //thanks epat, but it's goes looping forever on CTF map Silver Cascade Zone - HWR_QuickSortPlane(0, numplanes-1); -#endif - - gr_frontsector = NULL; //Hurdler: gr_fronsector is no longer valid - for (i = 0; i < numfloors; i++) - { - HWR_GetFlat(planeinfo[i].lumpnum); - HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].lumpnum, - planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap); - } - numfloors = 0; -} -#endif - -static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) +void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { static size_t allocedwalls = 0; @@ -6784,108 +4820,42 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I M_Memcpy(&wallinfo[numwalls].Surf, pSurf, sizeof (FSurfaceInfo)); wallinfo[numwalls].texnum = texnum; wallinfo[numwalls].blend = blend; -#ifdef SORTING wallinfo[numwalls].drawcount = drawcount++; -#endif wallinfo[numwalls].fogwall = fogwall; wallinfo[numwalls].lightlevel = lightlevel; wallinfo[numwalls].wallcolormap = wallcolormap; numwalls++; } -#ifndef SORTING -static void HWR_RenderTransparentWalls(void) + +void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { - size_t i; - - /*{ // sorting is disbale for now, do it! - INT32 permut = 1; - while (permut) - { - INT32 j; - for (j = 0, permut = 0; j < numwalls-1; j++) - { - if (ABS(wallinfo[j].fixedheight-dup_viewz) < ABS(wallinfo[j+1].fixedheight-dup_viewz)) - { - wallinfo_t temp; - M_Memcpy(&temp, &wallinfo[j+1], sizeof (wallinfo_t)); - M_Memcpy(&wallinfo[j+1], &wallinfo[j], sizeof (wallinfo_t)); - M_Memcpy(&wallinfo[j], &temp, sizeof (wallinfo_t)); - permut = 1; - } - } - } - }*/ - - for (i = 0; i < numwalls; i++) - { - HWR_GetTexture(wallinfo[i].texnum); - HWR_RenderWall(wallinfo[i].wallVerts, &wallinfo[i].Surf, wallinfo[i].blend, wallinfo[i].wall->fogwall, wallinfo[i].wall->lightlevel, wallinfo[i].wall->wallcolormap); - } - numwalls = 0; -} -#endif -static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) -{ - FOutVector trVerts[4]; - UINT8 i; - FOutVector *wv; - UINT8 alpha; - - // transform - wv = trVerts; - // it sounds really stupid to do this conversion with the new T&L code - // we should directly put the right information in the right structure - // wallVerts3D seems ok, doesn't need FOutVector - // also remove the light copy - for (i = 0; i < 4; i++, wv++, wallVerts++) - { - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - } - - alpha = pSurf->FlatColor.s.alpha; // retain the alpha + FBITFIELD blendmode = blend; + UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting + HWR_Lighting(pSurf, lightlevel, wallcolormap); - if (wallcolormap) - { - if (fogwall) - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, true, false); - else - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, false, false); - } - else - { - if (fogwall) - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, true, false); - else - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); - } + pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting - pSurf->FlatColor.s.alpha = alpha; // put the alpha back after lighting + HWD.pfnSetShader(2); // wall shader if (blend & PF_Environment) - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip|PF_Occlude); // PF_Occlude must be used for solid objects - else - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip); // No PF_Occlude means overlapping (incorrect) transparency + blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects + + if (fogwall) + { + blendmode |= PF_Fog; + HWD.pfnSetShader(6); // fog shader + } + + blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency + + HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode); #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); - -#ifdef ALAM_LIGHTING - //Hurdler: TODO: do static lighting using gr_curline->lm - HWR_WallLighting(trVerts); #endif -#endif -} - -INT32 HWR_GetTextureUsed(void) -{ - return HWD.pfnGetTextureUsed(); } void HWR_DoPostProcessor(player_t *player) @@ -6893,6 +4863,8 @@ void HWR_DoPostProcessor(player_t *player) postimg_t *type = &postimgtype[0]; UINT8 i; + HWD.pfnUnSetShader(); + for (i = splitscreen; i > 0; i--) { if (player == &players[displayplayers[i]]) @@ -6916,15 +4888,15 @@ void HWR_DoPostProcessor(player_t *player) // This won't change if the flash palettes are changed unfortunately, but it works for its purpose if (player->flashpal == PAL_NUKE) { - Surf.FlatColor.s.red = 0xff; - Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0x7F; // The nuke palette is kind of pink-ish + Surf.PolyColor.s.red = 0xff; + Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0x7F; // The nuke palette is kind of pink-ish } else - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; + Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = 0xc0; // match software mode + Surf.PolyColor.s.alpha = 0xc0; // match software mode - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Translucent|PF_NoTexture|PF_NoDepthTest); } // Capture the screen for intermission and screen waving @@ -6939,7 +4911,7 @@ void HWR_DoPostProcessor(player_t *player) { // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; - static double disStart = 0; + double disStart = leveltime; UINT8 x, y; INT32 WAVELENGTH; INT32 AMPLITUDE; @@ -6969,7 +4941,6 @@ void HWR_DoPostProcessor(player_t *player) } } HWD.pfnPostImgRedraw(v); - disStart += 1; // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) @@ -6980,14 +4951,11 @@ void HWR_DoPostProcessor(player_t *player) void HWR_StartScreenWipe(void) { - //CONS_Debug(DBG_RENDER, "In HWR_StartScreenWipe()\n"); HWD.pfnStartScreenWipe(); } void HWR_EndScreenWipe(void) { - HWRWipeCounter = 0.0f; - //CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n"); HWD.pfnEndScreenWipe(); } @@ -7021,13 +4989,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) } HWR_GetFadeMask(lumpnum); - HWD.pfnDoScreenWipe(); - - HWRWipeCounter += 0.05f; // increase opacity of end screen - - if (HWRWipeCounter > 1.0f) - HWRWipeCounter = 1.0f; } void HWR_MakeScreenFinalTexture(void) @@ -7040,4 +5002,161 @@ void HWR_DrawScreenFinalTexture(int width, int height) HWD.pfnDrawScreenFinalTexture(width, height); } +// jimita 18032019 +typedef struct +{ + char type[16]; + INT32 id; +} shaderxlat_t; + +static inline UINT16 HWR_CheckShader(UINT16 wadnum) +{ + UINT16 i; + lumpinfo_t *lump_p; + + lump_p = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name, "SHADERS", 7) == 0) + return i; + + return INT16_MAX; +} + +void HWR_LoadShaders(UINT16 wadnum, boolean PK3) +{ + UINT16 lump; + char *shaderdef, *line; + char *stoken; + char *value; + size_t size; + int linenum = 1; + 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); + if (lump == INT16_MAX) + return; + + shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + 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'; + + stoken = strtok(line, "\r\n "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); + goto skip_field; + } + + if (!stricmp(stoken, "GLSL")) + { + 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); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_lump; + } + + if (!stricmp(value, "VERTEX")) + shadertype = 1; + else if (!stricmp(value, "FRAGMENT")) + shadertype = 2; + +skip_lump: + stoken = strtok(NULL, "\r\n "); + linenum++; + } + else + { + 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); + 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); + Z_Free(line); + return; + } + + for (i = 0; i < SHADER_TYPES; i++) + { + if (!stricmp(shaderxlat[i].type, stoken)) + { + size_t shader_size; + char *shader_source; + char *shader_lumpname; + UINT16 shader_lumpnum; + + if (PK3) + { + shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL); + strcpy(shader_lumpname, "Shaders/sh_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0); + } + else + { + shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL); + strcpy(shader_lumpname, "SH_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0); + } + + 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); + Z_Free(shader_lumpname); + continue; + } + + shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum); + shader_source = Z_Malloc(shader_size, PU_STATIC, NULL); + W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source); + + HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2)); + + Z_Free(shader_source); + Z_Free(shader_lumpname); + } + } + +skip_field: + stoken = strtok(NULL, "\r\n= "); + linenum++; + } + } + + HWD.pfnInitCustomShaders(); + + Z_Free(line); + return; +} + #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 7bc361d9..bc4a74e5 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -17,9 +17,12 @@ /// \file /// \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" @@ -27,38 +30,51 @@ #include "../d_player.h" #include "../r_defs.h" +#define GLENCORE + // Startup & Shutdown the hardware mode renderer void HWR_Startup(void); void HWR_Shutdown(void); -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_RenderSkyboxView(INT32 viewnumber, player_t *player); -void HWR_RenderPlayerView(INT32 viewnumber, player_t *player); -void HWR_DrawViewBorder(INT32 clearlines); -void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); -UINT8 *HWR_GetScreenshot(void); -boolean HWR_Screenshot(const char *lbmname); -void HWR_InitTextureMapping(void); -void HWR_SetViewSize(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 scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); -void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); -void HWR_CreatePlanePolygons(INT32 bspnum); -void HWR_CreateStaticLightmaps(INT32 bspnum); -void HWR_PrepLevelCache(size_t pnumtextures); +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_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum); +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_DrawViewBorder(INT32 clearlines); +void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); +UINT8 *HWR_GetScreenshot(void); +boolean HWR_Screenshot(const char *lbmname); + +// 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); -void HWR_CorrectSWTricks(void); -void transform(float *cx, float *cy, float *cz); + +// 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 + FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); -INT32 HWR_GetTextureUsed(void); + +// hw_main.c: Post-rendering void HWR_DoPostProcessor(player_t *player); void HWR_StartScreenWipe(void); void HWR_EndScreenWipe(void); @@ -67,24 +83,60 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum); void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); -// This stuff is put here so MD2's can use them -UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); -FUNCMATH UINT8 LightLevelToLum(INT32 l); +// 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); -extern CV_PossibleValue_t granisotropicmode_cons_t[]; - -#ifdef ALAM_LIGHTING -extern consvar_t cv_grdynamiclighting; -extern consvar_t cv_grstaticlighting; -extern consvar_t cv_grcoronas; -extern consvar_t cv_grcoronasize; +#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 + +// 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); + +#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_grfallbackplayermodel; extern consvar_t cv_grfog; -extern consvar_t cv_grfogcolor; extern consvar_t cv_grfogdensity; -extern consvar_t cv_grsoftwarefog; extern consvar_t cv_grgammared; extern consvar_t cv_grgammagreen; extern consvar_t cv_grgammablue; @@ -94,22 +146,9 @@ 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 float gr_viewwidth, gr_viewheight, gr_baseviewwindowx, gr_baseviewwindowy; - -extern float gr_basewindowcenterx, gr_basewindowcentery; - -// BP: big hack for a test in lighting ref : 1249753487AB -extern fixed_t *hwbbox; -extern FTransform atransform; - -typedef struct -{ - wallVert3D floorVerts[4]; - FSurfaceInfo Surf; - INT32 texnum; - INT32 blend; - INT32 drawcount; -} floorinfo_t; +extern CV_PossibleValue_t granisotropicmode_cons_t[]; #endif diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d217f409..7d97bd06 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,17 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief MD2 Handling @@ -90,7 +85,6 @@ static void md2_freeModel (model_t *model) } #endif - // // load model // @@ -151,7 +145,7 @@ static void PNG_warn(png_structp PNG, png_const_charp pngtext) CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); } -static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_t *grpatch) +static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_t *grpatch) { png_structp png_ptr; png_infop png_info_ptr; @@ -205,7 +199,7 @@ static GrTextureFormat_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->grInfo.data); return 0; } #ifdef USE_FAR_KEYWORD @@ -246,7 +240,7 @@ static GrTextureFormat_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_HWRCACHE, &grpatch->mipmap->grInfo.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; @@ -285,7 +279,7 @@ typedef struct UINT8 filler[54]; } PcxHeader; -static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h, +static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h, GLPatch_t *grpatch) { PcxHeader header; @@ -326,7 +320,7 @@ static GrTextureFormat_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_HWRCACHE, &grpatch->mipmap->grInfo.data); if (fread(palette, sizeof (UINT8), PALSIZE, file) != PALSIZE) { @@ -374,37 +368,43 @@ static void md2_loadTexture(md2_t *model) if (model->grpatch) { grpatch = model->grpatch; - Z_Free(grpatch->mipmap.grInfo.data); + Z_Free(grpatch->mipmap->grInfo.data); } else + { grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO, &(model->grpatch)); + grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL); + } - if (!grpatch->mipmap.downloaded && !grpatch->mipmap.grInfo.data) + if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.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->grInfo.format = PNG_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->grInfo.format == 0) #endif - grpatch->mipmap.grInfo.format = PCX_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap.grInfo.format == 0) + grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->grInfo.format == 0) + { + grpatch->notfound = true;// mark it so its not searched for again repeatedly return; + } - grpatch->mipmap.downloaded = 0; - grpatch->mipmap.flags = 0; + grpatch->mipmap->downloaded = 0; + grpatch->mipmap->flags = 0; grpatch->width = (INT16)w; grpatch->height = (INT16)h; - grpatch->mipmap.width = (UINT16)w; - grpatch->mipmap.height = (UINT16)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; + 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); + HWD.pfnSetTexture(grpatch->mipmap); HWR_UnlockCachedPatch(grpatch); } @@ -422,40 +422,44 @@ static void md2_loadBlendTexture(md2_t *model) if (model->blendgrpatch) { grpatch = model->blendgrpatch; - Z_Free(grpatch->mipmap.grInfo.data); + Z_Free(grpatch->mipmap->grInfo.data); } else + { grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO, &(model->blendgrpatch)); + grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL); + } - if (!grpatch->mipmap.downloaded && !grpatch->mipmap.grInfo.data) + if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.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->grInfo.format = PNG_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->grInfo.format == 0) #endif - grpatch->mipmap.grInfo.format = PCX_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap.grInfo.format == 0) + grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->grInfo.format == 0) { + grpatch->notfound = true;// mark it so its not searched for again repeatedly Z_Free(filename); return; } - grpatch->mipmap.downloaded = 0; - grpatch->mipmap.flags = 0; + grpatch->mipmap->downloaded = 0; + grpatch->mipmap->flags = 0; grpatch->width = (INT16)w; grpatch->height = (INT16)h; - grpatch->mipmap.width = (UINT16)w; - grpatch->mipmap.height = (UINT16)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; + 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 + 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); @@ -544,7 +548,7 @@ void HWR_InitMD2(void) goto md2found; } } - // no sprite/player skin name found?!? + // no sprite/player skin name found?!?D CONS_Printf("Unknown sprite/player skin %s detected in mdls.dat\n", name); md2found: // move on to next line... @@ -579,7 +583,7 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup } } - // Check for any MD2s that match the names of player skins! + // Check for any MD2s that match the names of sprite names! while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) { if (stricmp(name, skins[skin].name) == 0) @@ -655,18 +659,26 @@ spritemd2found: // 0.0722 to blue // (See this same define in k_kart.c!) #define SETBRIGHTNESS(brightness,r,g,b) \ - brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color) { - UINT8 i; UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; + UINT8 translation[16]; // First the color index + UINT8 cutoff[16]; // Brightness cutoff before using the next color + UINT8 translen = 0; + UINT8 i; + UINT8 colorbrightnesses[16]; + UINT8 color_match_lookup[256]; // optimization attempt + + blendcolor = V_GetColor(0); // initialize + memset(translation, 0, sizeof(translation)); + memset(cutoff, 0, sizeof(cutoff)); if (grmip->width == 0) { - grmip->width = gpatch->width; grmip->height = gpatch->height; @@ -676,110 +688,323 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, grmip->grInfo.format = GR_RGBA; } - Z_Free(grmip->grInfo.data); - grmip->grInfo.data = NULL; + if (grmip->grInfo.data) + { + Z_Free(grmip->grInfo.data); + grmip->grInfo.data = NULL; + } cur = Z_Malloc(size*4, PU_HWRCACHE, &grmip->grInfo.data); memset(cur, 0x00, size*4); - image = gpatch->mipmap.grInfo.data; - blendimage = blendgpatch->mipmap.grInfo.data; + image = gpatch->mipmap->grInfo.data; + blendimage = blendgpatch->mipmap->grInfo.data; - // Average all of the translation's colors + // TC_METALSONIC includes an actual skincolor translation, on top of its flashing. + if (skinnum == TC_METALSONIC) + color = SKINCOLOR_BLUEBERRY; + + if (color != SKINCOLOR_NONE) { - const UINT8 div = 6; - const UINT8 start = 4; - UINT32 r, g, b; + UINT8 numdupes = 1; + UINT8 prevdupes = numdupes; - blendcolor = V_GetColor(colortranslations[color][start]); - r = (UINT32)(blendcolor.s.red*blendcolor.s.red); - g = (UINT32)(blendcolor.s.green*blendcolor.s.green); - b = (UINT32)(blendcolor.s.blue*blendcolor.s.blue); + translation[translen] = colortranslations[color][0]; + cutoff[translen] = 255; - for (i = 1; i < div; i++) + for (i = 1; i < 16; i++) { - RGBA_t nextcolor = V_GetColor(colortranslations[color][start+i]); - r += (UINT32)(nextcolor.s.red*nextcolor.s.red); - g += (UINT32)(nextcolor.s.green*nextcolor.s.green); - b += (UINT32)(nextcolor.s.blue*nextcolor.s.blue); + if (translation[translen] == colortranslations[color][i]) + { + numdupes++; + continue; + } + + if (translen > 0) + { + INT16 newcutoff = cutoff[translen-1] - (255 / (16 / prevdupes)); + + if (newcutoff < 0) + newcutoff = 0; + + cutoff[translen] = (UINT8)newcutoff; + } + + prevdupes = numdupes; + numdupes = 1; + translen++; + + translation[translen] = (UINT8)colortranslations[color][i]; } - blendcolor.s.red = (UINT8)(FixedSqrt((r/div)<>FRACBITS); - blendcolor.s.green = (UINT8)(FixedSqrt((g/div)<>FRACBITS); - blendcolor.s.blue = (UINT8)(FixedSqrt((b/div)<>FRACBITS); + translen++; } - // rainbow support, could theoretically support boss ones too - if (skinnum == TC_RAINBOW) + if (skinnum == TC_RAINBOW && translen > 0) { - while (size--) + UINT16 b; + INT32 compare; + + for (i = 0; i < translen; i++) // moved from inside the loop to here { - if (image->s.alpha == 0 && blendimage->s.alpha == 0) + RGBA_t tempc = V_GetColor(translation[i]); + SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison + } + // generate lookup table for color brightness matching + for (b = 0; b < 256; b++) + { + UINT16 brightdif = 256; + + color_match_lookup[i] = 0; + for (i = 0; i < translen; i++) { - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 - cur->rgba = image->rgba; + if (b > 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)(b)); + + if (compare < brightdif) + { + brightdif = (UINT16)compare; + color_match_lookup[b] = i; // best matching color that's equal brightness or darker + } + } + } + } + + while (size--) + { + if (skinnum == TC_BOSS) + { + // Turn everything below a certain threshold white + if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue < 127) + { + // Lactozilla: Invert the colors + cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue); } else + { + cur->s.red = image->s.red; + cur->s.green = image->s.green; + cur->s.blue = image->s.blue; + } + + cur->s.alpha = image->s.alpha; + } + else if (skinnum == TC_ALLWHITE) + { + // Turn everything white + cur->s.red = cur->s.green = cur->s.blue = 255; + cur->s.alpha = image->s.alpha; + } + else + { + // All settings that use skincolors! + UINT16 brightness; + + // Everything below requires a blend image + if (blendimage == NULL) + { + cur->rgba = image->rgba; + 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) + { + if (image->s.alpha == 0 && blendimage->s.alpha == 0) + { + cur->rgba = image->rgba; + goto skippixel; + } + else + { + UINT16 imagebright, blendbright; + SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); + SETBRIGHTNESS(blendbright,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 + { + SETBRIGHTNESS(brightness,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; + } + + blendcolor = V_GetColor(translation[firsti]); + + 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; + } + } + + if (skinnum == TC_RAINBOW) { UINT32 tempcolor; - UINT16 imagebright, blendbright, finalbright, colorbright; - SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); - SETBRIGHTNESS(blendbright,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 - finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; - SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); + UINT16 colorbright; - tempcolor = (finalbright*blendcolor.s.red)/colorbright; + SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); + if (colorbright == 0) + colorbright = 1; // no dividing by 0 please + + tempcolor = (brightness * blendcolor.s.red) / colorbright; tempcolor = min(255, tempcolor); cur->s.red = (UINT8)tempcolor; - tempcolor = (finalbright*blendcolor.s.green)/colorbright; + + tempcolor = (brightness * blendcolor.s.green) / colorbright; tempcolor = min(255, tempcolor); cur->s.green = (UINT8)tempcolor; - tempcolor = (finalbright*blendcolor.s.blue)/colorbright; + + tempcolor = (brightness * blendcolor.s.blue) / colorbright; tempcolor = min(255, tempcolor); cur->s.blue = (UINT8)tempcolor; cur->s.alpha = image->s.alpha; } - - cur++; image++; blendimage++; - } - } - else - { - while (size--) - { - if (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 { + // Color strength depends on image alpha INT32 tempcolor; - INT16 tempmult, tempalpha; - tempalpha = -(abs(blendimage->s.red-127)-127)*2; - if (tempalpha > 255) - tempalpha = 255; - else if (tempalpha < 0) - tempalpha = 0; - tempmult = (blendimage->s.red-127)*2; - if (tempmult > 255) - tempmult = 255; - else if (tempmult < 0) - tempmult = 0; - - tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255; + 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 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255; + + 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 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255; + + 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; } - cur++; image++; blendimage++; +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) + { + // 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++; image++; + + if (blendimage != NULL) + blendimage++; } return; @@ -795,13 +1020,13 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT if (colormap == colormaps || colormap == NULL) { // Don't do any blending - HWD.pfnSetTexture(&gpatch->mipmap); + HWD.pfnSetTexture(gpatch->mipmap); return; } // search for the mimmap // skip the first (no colormap translated) - for (grmip = &gpatch->mipmap; grmip->nextcolormap; ) + for (grmip = gpatch->mipmap; grmip->nextcolormap; ) { grmip = grmip->nextcolormap; if (grmip->colormap == colormap) @@ -837,35 +1062,19 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT // -----------------+ // HWR_DrawMD2 : Draw MD2 -// : (monsters, bonuses, weapons, lights, ...) +// : // Returns : // -----------------+ - /* - wait/stand - death - pain - walk - shoot/fire - die? - atka? - atkb? - attacka/b/c/d? - res? - run? - */ -#define NORMALFOG 0x00000000 -#define FADEFOG 0x19000000 void HWR_DrawMD2(gr_vissprite_t *spr) { - FSurfaceInfo Surf; + md2_t *md2; char filename[64]; INT32 frame = 0; INT32 nextFrame = -1; FTransform p; - md2_t *md2; - UINT8 color[4]; + FSurfaceInfo Surf; if (!cv_grmdls.value) return; @@ -878,8 +1087,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (spr->mobj->subsector) { sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel = 255; extracolormap_t *colormap = sector->extra_colormap; + UINT8 lightlevel = 255; if (sector->numlights) { @@ -902,14 +1111,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) colormap = sector->extra_colormap; } - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); } else { - Surf.FlatColor.rgba = 0xFFFFFFFF; + Surf.PolyColor.rgba = 0xFFFFFFFF; } // Look at HWR_ProjectSprite for more @@ -928,11 +1134,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) //durs = tics; if (spr->mobj->flags2 & MF2_SHADOW) - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; else if (spr->mobj->frame & FF_TRANSMASK) HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; // dont forget to enabled the depth test because we can't do this like // before: polygons models are not sorted @@ -967,22 +1173,23 @@ void HWR_DrawMD2(gr_vissprite_t *spr) return; } } - //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) + 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)) + 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->grInfo.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 + 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; @@ -1013,7 +1220,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else { // This is safe, since we know the texture has been downloaded - HWD.pfnSetTexture(&gpatch->mipmap); + HWD.pfnSetTexture(gpatch->mipmap); } } else @@ -1103,11 +1310,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr) } #endif - color[0] = Surf.FlatColor.s.red; - color[1] = Surf.FlatColor.s.green; - color[2] = Surf.FlatColor.s.blue; - color[3] = Surf.FlatColor.s.alpha; - // SRB2CBTODO: MD2 scaling support finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); @@ -1116,7 +1318,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.mirror = atransform.mirror; // from Kart #endif - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); + HWD.pfnSetShader(4); // model shader + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf); } } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 57d8026b..fab8e6ad 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -1,18 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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; 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 /// \brief MD2 Handling diff --git a/src/hardware/hw_trick.c b/src/hardware/hw_trick.c index 97d86b94..de4a76c5 100644 --- a/src/hardware/hw_trick.c +++ b/src/hardware/hw_trick.c @@ -44,6 +44,7 @@ #include "../doomstat.h" #ifdef HWRENDER +#include "hw_main.h" #include "hw_glob.h" #include "hw_dll.h" #include "../r_local.h" diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 9fcc8d15..5dc46099 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1,18 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// 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-2018 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 /// \brief OpenGL API for Sonic Robo Blast 2 @@ -32,6 +26,8 @@ #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 @@ -49,8 +45,7 @@ static const GLubyte white[4] = { 255, 255, 255, 255 }; // ========================================================================== // With OpenGL 1.1+, the first texture should be 1 -#define NOTEXTURE_NUM 1 // small white texture -#define FIRST_TEX_AVAIL (NOTEXTURE_NUM + 1) +#define NOTEXTURE_NUM 0 #define N_PI_DEMI (M_PIl/2.0f) //(1.5707963268f) @@ -63,13 +58,8 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; // ************************************************************************** -static GLuint NextTexAvail = FIRST_TEX_AVAIL; static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; -#if 0 -static GLuint pal_col = 0; -static FRGBAFloat const_pal_col; -#endif static FBITFIELD CurrentPolyFlags; static FTextureInfo* gr_cachetail = NULL; @@ -87,30 +77,28 @@ static GLint mag_filter = GL_LINEAR; static GLint anisotropic_filter = 0; static FTransform md2_transform; +const GLubyte *gl_version = NULL; +const GLubyte *gl_renderer = NULL; 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]; +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 -// Yay for arbitrary numbers! NextTexAvail is buggy for some reason. // 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 -// TODO: Store them in a more normal way -#define SCRTEX_SCREENTEXTURE 4294967295U -#define SCRTEX_STARTSCREENWIPE 4294967294U -#define SCRTEX_ENDSCREENWIPE 4294967293U -#define SCRTEX_FINALSCREENTEXTURE 4294967292U static GLuint screentexture = 0; static GLuint startScreenWipe = 0; static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; -#if 0 -GLuint screentexture = FIRST_TEX_AVAIL; -#endif // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { @@ -148,31 +136,32 @@ static const GLfloat byte2float[256] = { 0.972549f, 0.976471f, 0.980392f, 0.984314f, 0.988235f, 0.992157f, 0.996078f, 1.000000f }; -float byteasfloat(UINT8 fbyte) -{ - return (float)(byte2float[fbyte]*2.0f); -} - -static I_Error_t I_Error_GL = NULL; - // -----------------+ -// DBG_Printf : Output error messages to debug log if DEBUG_TO_FILE is defined, +// GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, // : else do nothing // Returns : // -----------------+ -FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) + +#ifdef DEBUG_TO_FILE +FILE *gllogstream; +#endif + +FUNCPRINTF void GL_DBG_Printf(const char *format, ...) { #ifdef DEBUG_TO_FILE - char str[4096] = ""; + char str[4096] = ""; va_list arglist; - va_start (arglist, lpFmt); - vsnprintf (str, 4096, lpFmt, arglist); - va_end (arglist); - if (gllogstream) - fwrite(str, strlen(str), 1, gllogstream); + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + + fwrite(str, strlen(str), 1, gllogstream); #else - (void)lpFmt; + (void)format; #endif } @@ -190,9 +179,6 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglEnable glEnable #define pglDisable glDisable #define pglGetFloatv glGetFloatv -//glGetIntegerv -//glGetString -#define pglHint glHint /* Depth Buffer */ #define pglClearDepth glClearDepth @@ -206,7 +192,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglPushMatrix glPushMatrix #define pglPopMatrix glPopMatrix #define pglLoadIdentity glLoadIdentity -#define pglMultMatrixf glMultMatrixf +#define pglMultMatrixd glMultMatrixd #define pglRotatef glRotatef #define pglScalef glScalef #define pglTranslatef glTranslatef @@ -231,6 +217,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglLightfv glLightfv #define pglLightModelfv glLightModelfv #define pglMaterialfv glMaterialfv +#define pglMateriali glMateriali /* Raster functions */ #define pglPixelStorei glPixelStorei @@ -247,6 +234,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object +#define pglGenTextures glGenTextures #define pglDeleteTextures glDeleteTextures #define pglBindTexture glBindTexture /* texture mapping */ //GL_EXT_copy_texture @@ -259,7 +247,6 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) /* Miscellaneous */ typedef void (APIENTRY * PFNglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); static PFNglClearColor pglClearColor; -//glClear typedef void (APIENTRY * PFNglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); static PFNglColorMask pglColorMask; typedef void (APIENTRY * PFNglAlphaFunc) (GLenum func, GLclampf ref); @@ -278,8 +265,6 @@ typedef void (APIENTRY * PFNglDisable) (GLenum cap); static PFNglDisable pglDisable; typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params); static PFNglGetFloatv pglGetFloatv; -//glGetIntegerv -//glGetString /* Depth Buffer */ typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth); @@ -337,7 +322,6 @@ static PFNglBufferData pglBufferData; typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); static PFNglDeleteBuffers pglDeleteBuffers; - /* Lighting */ typedef void (APIENTRY * PFNglShadeModel) (GLenum mode); static PFNglShadeModel pglShadeModel; @@ -347,6 +331,8 @@ typedef void (APIENTRY * PFNglLightModelfv) (GLenum pname, GLfloat *params); static PFNglLightModelfv pglLightModelfv; typedef void (APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *params); static PFNglMaterialfv pglMaterialfv; +typedef void (APIENTRY * PFNglMateriali) (GLint face, GLenum pname, GLint param); +static PFNglMateriali pglMateriali; /* Raster functions */ typedef void (APIENTRY * PFNglPixelStorei) (GLenum pname, GLint param); @@ -370,6 +356,8 @@ static PFNglFogfv pglFogfv; /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object +typedef void (APIENTRY * PFNglGenTextures) (GLsizei n, const GLuint *textures); +static PFNglGenTextures pglGenTextures; typedef void (APIENTRY * PFNglDeleteTextures) (GLsizei n, const GLuint *textures); static PFNglDeleteTextures pglDeleteTextures; typedef void (APIENTRY * PFNglBindTexture) (GLenum target, GLuint texture); @@ -394,6 +382,10 @@ 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.2 Parms */ /* GL_CLAMP_TO_EDGE_EXT */ #ifndef GL_CLAMP_TO_EDGE @@ -421,7 +413,7 @@ boolean SetupGLfunc(void) func = GetGLFunc(#proc); \ if (!func) \ { \ - DBG_Printf("failed to get OpenGL function: %s", #proc); \ + GL_DBG_Printf("failed to get OpenGL function: %s\n", #proc); \ } \ GETOPENGLFUNC(pglClearColor, glClearColor) @@ -439,22 +431,23 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv) GETOPENGLFUNC(pglGetString, glGetString) - GETOPENGLFUNC(pglClearDepth , glClearDepth) - GETOPENGLFUNC(pglDepthFunc , glDepthFunc) - GETOPENGLFUNC(pglDepthMask , glDepthMask) - GETOPENGLFUNC(pglDepthRange , glDepthRange) + GETOPENGLFUNC(pglClearDepth, glClearDepth) + GETOPENGLFUNC(pglDepthFunc, glDepthFunc) + GETOPENGLFUNC(pglDepthMask, glDepthMask) + GETOPENGLFUNC(pglDepthRange, glDepthRange) - GETOPENGLFUNC(pglMatrixMode , glMatrixMode) - GETOPENGLFUNC(pglViewport , glViewport) - GETOPENGLFUNC(pglPushMatrix , glPushMatrix) - GETOPENGLFUNC(pglPopMatrix , glPopMatrix) - GETOPENGLFUNC(pglLoadIdentity , glLoadIdentity) - GETOPENGLFUNC(pglMultMatrixf , glMultMatrixf) - GETOPENGLFUNC(pglRotatef , glRotatef) - GETOPENGLFUNC(pglScalef , glScalef) - GETOPENGLFUNC(pglTranslatef , glTranslatef) + GETOPENGLFUNC(pglMatrixMode, glMatrixMode) + GETOPENGLFUNC(pglViewport, glViewport) + GETOPENGLFUNC(pglPushMatrix, glPushMatrix) + GETOPENGLFUNC(pglPopMatrix, glPopMatrix) + GETOPENGLFUNC(pglLoadIdentity, glLoadIdentity) + GETOPENGLFUNC(pglMultMatrixf, glMultMatrixf) + GETOPENGLFUNC(pglRotatef, glRotatef) + GETOPENGLFUNC(pglScalef, glScalef) + GETOPENGLFUNC(pglTranslatef, glTranslatef) GETOPENGLFUNC(pglColor4ubv, glColor4ubv) + GETOPENGLFUNC(pglVertexPointer, glVertexPointer) GETOPENGLFUNC(pglNormalPointer, glNormalPointer) GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) @@ -463,38 +456,329 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglEnableClientState, glEnableClientState) GETOPENGLFUNC(pglDisableClientState, glDisableClientState) - GETOPENGLFUNC(pglShadeModel , glShadeModel) + GETOPENGLFUNC(pglShadeModel, glShadeModel) GETOPENGLFUNC(pglLightfv, glLightfv) - GETOPENGLFUNC(pglLightModelfv , glLightModelfv) - GETOPENGLFUNC(pglMaterialfv , glMaterialfv) + GETOPENGLFUNC(pglLightModelfv, glLightModelfv) + GETOPENGLFUNC(pglMaterialfv, glMaterialfv) + GETOPENGLFUNC(pglMateriali, glMateriali) - GETOPENGLFUNC(pglPixelStorei , glPixelStorei) - GETOPENGLFUNC(pglReadPixels , glReadPixels) + GETOPENGLFUNC(pglPixelStorei, glPixelStorei) + GETOPENGLFUNC(pglReadPixels, glReadPixels) - GETOPENGLFUNC(pglTexEnvi , glTexEnvi) - GETOPENGLFUNC(pglTexParameteri , glTexParameteri) - GETOPENGLFUNC(pglTexImage2D , glTexImage2D) + GETOPENGLFUNC(pglTexEnvi, glTexEnvi) + GETOPENGLFUNC(pglTexParameteri, glTexParameteri) + GETOPENGLFUNC(pglTexImage2D, glTexImage2D) - GETOPENGLFUNC(pglFogf , glFogf) - GETOPENGLFUNC(pglFogfv , glFogfv) + GETOPENGLFUNC(pglFogf, glFogf) + GETOPENGLFUNC(pglFogfv, glFogfv) - GETOPENGLFUNC(pglDeleteTextures , glDeleteTextures) - GETOPENGLFUNC(pglBindTexture , glBindTexture) + GETOPENGLFUNC(pglGenTextures, glGenTextures) + GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) + GETOPENGLFUNC(pglBindTexture, glBindTexture) - GETOPENGLFUNC(pglCopyTexImage2D , glCopyTexImage2D) - GETOPENGLFUNC(pglCopyTexSubImage2D , glCopyTexSubImage2D) + GETOPENGLFUNC(pglCopyTexImage2D, glCopyTexImage2D) + GETOPENGLFUNC(pglCopyTexSubImage2D, glCopyTexSubImage2D) #undef GETOPENGLFUNC - - pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); - #endif return true; } -// This has to be done after the context is created so the version number can be obtained -// This is stupid -- even some of the oldest usable OpenGL hardware today supports 1.3-level featureset. -boolean SetupGLFunc13(void) +#ifdef GL_SHADERS +typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); +typedef void (APIENTRY *PFNglShaderSource) (GLuint, GLsizei, const GLchar**, GLint*); +typedef void (APIENTRY *PFNglCompileShader) (GLuint); +typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*); +typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); +typedef void (APIENTRY *PFNglDeleteShader) (GLuint); +typedef GLuint (APIENTRY *PFNglCreateProgram) (void); +typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint); +typedef void (APIENTRY *PFNglLinkProgram) (GLuint); +typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); +typedef void (APIENTRY *PFNglUseProgram) (GLuint); +typedef void (APIENTRY *PFNglUniform1i) (GLint, GLint); +typedef void (APIENTRY *PFNglUniform1f) (GLint, GLfloat); +typedef void (APIENTRY *PFNglUniform2f) (GLint, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform3f) (GLint, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform4f) (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform1fv) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY *PFNglUniform2fv) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY *PFNglUniform3fv) (GLint, GLsizei, const GLfloat*); +typedef GLint (APIENTRY *PFNglGetUniformLocation) (GLuint, const GLchar*); + +static PFNglCreateShader pglCreateShader; +static PFNglShaderSource pglShaderSource; +static PFNglCompileShader pglCompileShader; +static PFNglGetShaderiv pglGetShaderiv; +static PFNglGetShaderInfoLog pglGetShaderInfoLog; +static PFNglDeleteShader pglDeleteShader; +static PFNglCreateProgram pglCreateProgram; +static PFNglAttachShader pglAttachShader; +static PFNglLinkProgram pglLinkProgram; +static PFNglGetProgramiv pglGetProgramiv; +static PFNglUseProgram pglUseProgram; +static PFNglUniform1i pglUniform1i; +static PFNglUniform1f pglUniform1f; +static PFNglUniform2f pglUniform2f; +static PFNglUniform3f pglUniform3f; +static PFNglUniform4f pglUniform4f; +static PFNglUniform1fv pglUniform1fv; +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? + +// 13062019 +typedef enum +{ + // lighting + gluniform_poly_color, + gluniform_tint_color, + gluniform_fade_color, + gluniform_lighting, + gluniform_fade_start, + gluniform_fade_end, + + // misc. (custom shaders) + gluniform_leveltime, + + gluniform_max, +} gluniform_t; + +typedef struct gl_shaderprogram_s +{ + GLuint program; + boolean custom; + GLint uniforms[gluniform_max+1]; +} gl_shaderprogram_t; +static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; + +// ======================== +// Fragment shader macros +// ======================== + +// +// GLSL Software fragment shader +// + +#define GLSL_DOOM_COLORMAP \ + "float R_DoomColormap(float light, float z)\n" \ + "{\n" \ + "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ + "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ + "float startmap = (15.0 - lightnum) * 4.0;\n" \ + "float scale = 160.0 / (lightz + 1.0);\n" \ + "return startmap - scale * 0.5;\n" \ + "}\n" + +#define GLSL_DOOM_LIGHT_EQUATION \ + "float R_DoomLightingEquation(float light)\n" \ + "{\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ + "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ + "}\n" + +#define GLSL_SOFTWARE_TINT_EQUATION \ + "if (tint_color.a > 0.0) {\n" \ + "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ + "float strength = sqrt(9.0 * tint_color.a);\n" \ + "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ + "}\n" + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(lighting);\n" \ + "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ + "float fs = fade_start / 31.0;\n" \ + "float fe = fade_end / 31.0;\n" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "final_color = mix(final_color, fade_color, darkness);\n" + +#define GLSL_SOFTWARE_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.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Water surface shader +// +// Mostly guesstimated, rather than the rest being built off Software science. +// Still needs to distort things underneath/around the water... +// + +#define GLSL_WATER_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" \ + "uniform float leveltime;\n" \ + "const float freq = 0.025;\n" \ + "const float amp = 0.025;\n" \ + "const float speed = 2.0;\n" \ + "const float pi = 3.14159;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ + "float a = -pi * (z * freq) + (leveltime * speed);\n" \ + "float sdistort = sin(a) * amp;\n" \ + "float cdistort = cos(a) * amp;\n" \ + "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +#define GLSL_FOG_FRAGMENT_SHADER \ + "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 base_color = gl_Color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// GLSL 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" + +static const char *fragment_shaders[] = { + // Default fragment shader + GLSL_DEFAULT_FRAGMENT_SHADER, + + // Floor fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Wall fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Sprite fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Model fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Water fragment shader + GLSL_WATER_FRAGMENT_SHADER, + + // Fog fragment shader + GLSL_FOG_FRAGMENT_SHADER, + + // Sky fragment shader + "uniform sampler2D tex;\n" + "void main(void) {\n" + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" + "}\0", + + NULL, +}; + +// ====================== +// Vertex shader macros +// ====================== + +// +// 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, +}; + +#endif // GL_SHADERS + +void SetupGLFunc4(void) { pglActiveTexture = GetGLFunc("glActiveTexture"); pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); @@ -504,17 +788,224 @@ boolean SetupGLFunc13(void) pglBindBuffer = GetGLFunc("glBindBuffer"); pglBufferData = GetGLFunc("glBufferData"); pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); + pglColorPointer = GetGLFunc("glColorPointer"); +#ifdef GL_SHADERS + pglCreateShader = GetGLFunc("glCreateShader"); + pglShaderSource = GetGLFunc("glShaderSource"); + pglCompileShader = GetGLFunc("glCompileShader"); + pglGetShaderiv = GetGLFunc("glGetShaderiv"); + pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog"); + pglDeleteShader = GetGLFunc("glDeleteShader"); + pglCreateProgram = GetGLFunc("glCreateProgram"); + pglAttachShader = GetGLFunc("glAttachShader"); + pglLinkProgram = GetGLFunc("glLinkProgram"); + pglGetProgramiv = GetGLFunc("glGetProgramiv"); + pglUseProgram = GetGLFunc("glUseProgram"); + pglUniform1i = GetGLFunc("glUniform1i"); + pglUniform1f = GetGLFunc("glUniform1f"); + pglUniform2f = GetGLFunc("glUniform2f"); + pglUniform3f = GetGLFunc("glUniform3f"); + pglUniform4f = GetGLFunc("glUniform4f"); + pglUniform1fv = GetGLFunc("glUniform1fv"); + pglUniform2fv = GetGLFunc("glUniform2fv"); + pglUniform3fv = GetGLFunc("glUniform3fv"); + pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); +#endif + + // GLU + pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); +} + +// jimita +EXPORT boolean HWRAPI(LoadShaders) (void) +{ +#ifdef GL_SHADERS + GLuint gl_vertShader, gl_fragShader; + GLint i, result; + + if (!pglUseProgram) return false; + + gl_customvertexshaders[0] = NULL; + gl_customfragmentshaders[0] = NULL; + + for (i = 0; vertex_shaders[i] && fragment_shaders[i]; 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)); + + // 18032019 + if (gl_customvertexshaders[i]) + vert_shader = gl_customvertexshaders[i]; + if (gl_customfragmentshaders[i]) + frag_shader = gl_customfragmentshaders[i]; + + if (i >= MAXSHADERS) + break; + if (i >= MAXSHADERPROGRAMS) + break; + + // + // Load and compile vertex shader + // + gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); + if (!gl_vertShader) + I_Error("Hardware driver: Error creating vertex shader %d", i); + + pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); + pglCompileShader(gl_vertShader); + + // check for compile errors + 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); + } + + // + // Load and compile fragment shader + // + gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); + if (!gl_fragShader) + I_Error("Hardware driver: Error creating fragment shader %d", i); + + pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); + pglCompileShader(gl_fragShader); + + // check for compile errors + 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 = &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); + + // 13062019 +#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); + + // lighting + shader->uniforms[gluniform_poly_color] = GETUNI("poly_color"); + shader->uniforms[gluniform_tint_color] = GETUNI("tint_color"); + shader->uniforms[gluniform_fade_color] = GETUNI("fade_color"); + shader->uniforms[gluniform_lighting] = GETUNI("lighting"); + shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); + shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); + + // misc. (custom shaders) + shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); + +#undef GETUNI + } +#endif return true; } +// +// Custom shader loading +// +EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment) +{ +#ifdef GL_SHADERS + if (!pglUseProgram) return; + if (number < 1 || number > MAXSHADERS) + I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS); + + if (fragment) + { + gl_customfragmentshaders[number] = malloc(size+1); + strncpy(gl_customfragmentshaders[number], shader, size); + gl_customfragmentshaders[number][size] = 0; + } + else + { + gl_customvertexshaders[number] = malloc(size+1); + strncpy(gl_customvertexshaders[number], shader, size); + gl_customvertexshaders[number][size] = 0; + } +#endif +} + +EXPORT void HWRAPI(InitCustomShaders) (void) +{ +#ifdef GL_SHADERS + KillShaders(); + LoadShaders(); +#endif +} + +EXPORT void HWRAPI(SetShader) (int shader) +{ +#ifdef GL_SHADERS + if (gl_allowshaders) + { + gl_shadersenabled = true; + if ((GLuint)shader != gl_currentshaderprogram) + { + gl_currentshaderprogram = shader; + gl_shaderprogramchanged = true; + } + } + else +#endif + gl_shadersenabled = false; +} + +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) +{ + // unused......................... +} + // -----------------+ // SetNoTexture : Disable texture // -----------------+ static void SetNoTexture(void) { - // Set small white texture. - if (tex_downloaded != NOTEXTURE_NUM) + // Disable texture. + if (tex_downloaded != NOTEXTURE_NUM && !gl_batching) { pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM); tex_downloaded = NOTEXTURE_NUM; @@ -533,7 +1024,7 @@ static void GLPerspective(GLfloat fovy, GLfloat aspect) const GLfloat zNear = NEAR_CLIPPING_PLANE; const GLfloat zFar = FAR_CLIPPING_PLANE; const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f); - const GLfloat sine = sinf(radians); + const GLfloat sine = sin(radians); const GLfloat deltaZ = zFar - zNear; GLfloat cotangent; @@ -547,56 +1038,15 @@ 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) { -// 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) @@ -617,128 +1067,64 @@ void SetModelView(GLint w, GLint h) pglLoadIdentity(); GLPerspective(fov, ASPECT_RATIO); - //pglScalef(1.0f, 320.0f/200.0f, 1.0f); // gr_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) { - // Bind little white RGBA texture to ID NOTEXTURE_NUM. - /* - FUINT Data[8*8]; - INT32 i; - */ -#ifdef GL_LIGHT_MODEL_AMBIENT - GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; -#endif - -// 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); pglDepthRange(0.0f, 1.0f); pglDepthFunc(GL_LEQUAL); - // this set CurrentPolyFlags to the acctual configuration + // this set CurrentPolyFlags to the actual configuration CurrentPolyFlags = 0xffffffff; SetBlend(0); - /* - for (i = 0; i < 64; i++) - Data[i] = 0xffFFffFF; // white pixel - */ - - tex_downloaded = (GLuint)-1; + //tex_downloaded = (GLuint)-1; SetNoTexture(); - //pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM); - //tex_downloaded = NOTEXTURE_NUM; - //pglTexImage2D(GL_TEXTURE_2D, 0, 4, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, Data); pglPolygonOffset(-1.0f, -1.0f); - //pglEnable(GL_CULL_FACE); - //pglCullFace(GL_FRONT); - - //glFogi(GL_FOG_MODE, GL_EXP); - //pglHint(GL_FOG_HINT, GL_FASTEST); - //pglFogfv(GL_FOG_COLOR, fogcolor); - //pglFogf(GL_FOG_DENSITY, 0.0005f); - - // 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) { - //DBG_Printf ("HWR_Flush()\n"); + //GL_DBG_Printf("HWR_Flush()\n"); while (gr_cachehead) { // ceci n'est pas du tout necessaire vu que tu les a charger normalement et // donc il sont dans ta liste ! -#if 0 - //Hurdler: 25/04/2000: now support colormap in hardware mode - FTextureInfo *tmp = gr_cachehead->nextskin; - - // The memory should be freed in the main code - while (tmp) - { - pglDeleteTextures(1, &tmp->downloaded); - tmp->downloaded = 0; - tmp = tmp->nextcolormap; - } -#endif - pglDeleteTextures(1, (GLuint *)&gr_cachehead->downloaded); + if (gr_cachehead->downloaded) + pglDeleteTextures(1, (GLuint *)&gr_cachehead->downloaded); gr_cachehead->downloaded = 0; gr_cachehead = gr_cachehead->nextmipmap; } gr_cachetail = gr_cachehead = NULL; //Hurdler: well, gr_cachehead is already NULL - NextTexAvail = FIRST_TEX_AVAIL; -#if 0 - if (screentexture != FIRST_TEX_AVAIL) - { - pglDeleteTextures(1, &screentexture); - screentexture = FIRST_TEX_AVAIL; - } -#endif tex_downloaded = 0; } @@ -776,10 +1162,8 @@ INT32 isExtAvailable(const char *extension, const GLubyte *start) // Init : Initialise the OpenGL interface API // Returns : // -----------------+ -EXPORT boolean HWRAPI(Init) (I_Error_t FatalErrorFunction) +EXPORT boolean HWRAPI(Init) (void) { - I_Error_GL = FatalErrorFunction; - DBG_Printf ("%s %s\n", DRIVER_STRING, VERSIONSTRING); return LoadGL(); } @@ -789,7 +1173,6 @@ EXPORT boolean HWRAPI(Init) (I_Error_t FatalErrorFunction) // -----------------+ EXPORT void HWRAPI(ClearMipMapCache) (void) { - // DBG_Printf ("HWR_Flush(exe)\n"); Flush(); } @@ -803,7 +1186,7 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 * dst_data) { INT32 i; - // 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); @@ -851,7 +1234,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) { - // 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; @@ -875,7 +1258,7 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat * ClearColor) { - // DBG_Printf ("ClearBuffer(%d)\n", alpha); + //GL_DBG_Printf("ClearBuffer(%d)\n", alpha); GLbitfield ClearMask = 0; if (ColorMask) @@ -910,7 +1293,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, F2DCoord * v2, RGBA_t Color) { - // DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); + //GL_DBG_Printf("DrawLine(): %f %f, %f %f\n", v1->x, v1->y, v2->x, v2->y); GLfloat p[12]; GLfloat dx, dy; GLfloat angle; @@ -1002,7 +1385,6 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) break; } } - if (Xor & PF_NoAlphaTest) { if (PolyFlags & PF_NoAlphaTest) @@ -1018,7 +1400,6 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) else pglDisable(GL_POLYGON_OFFSET_FILL); } - if (Xor&PF_NoDepthTest) { if (PolyFlags & PF_NoDepthTest) @@ -1055,22 +1436,19 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) } else #endif + + // mix texture colour with Surface->PolyColor if (PolyFlags & PF_Modulated) - { // mix texture colour with Surface->FlatColor 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); } @@ -1088,9 +1466,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) } } if (PolyFlags & PF_NoTexture) - { SetNoTexture(); - } } CurrentPolyFlags = PolyFlags; } @@ -1110,7 +1486,8 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) { if (pTexInfo->downloaded != tex_downloaded) { - pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); + if (!gl_batching) + pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); tex_downloaded = pTexInfo->downloaded; } } @@ -1120,12 +1497,25 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) static RGBA_t tex[2048*2048]; const GLvoid *ptex = tex; INT32 w, h; + GLuint texnum = 0; - //DBG_Printf ("DownloadMipmap %d %x\n",NextTexAvail,pTexInfo->grInfo.data); + 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)) { @@ -1207,11 +1597,12 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } else - DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); + GL_DBG_Printf("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); - pTexInfo->downloaded = NextTexAvail++; - tex_downloaded = pTexInfo->downloaded; - pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); + // 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) @@ -1225,6 +1616,17 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) 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); @@ -1309,102 +1711,886 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } +static void load_shaders(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +{ +#ifdef GL_SHADERS + if (gl_shadersenabled && pglUseProgram) + { + 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 (!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 + } + } + else + pglUseProgram(0); + } +#endif +} + +// unfinished draw call batching + +// Note: could use realloc in the array reallocation code + +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; + GLuint texNum; + GLuint shader; +} PolygonArrayEntry; + +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; +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) + { + 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)); + } + // drawing functions will now collect the drawing data instead of passing it to opengl + gl_batching = true; + //CONS_Printf("StartBatching end\n"); +} + +static int comparePolygons(const void *p1, const void *p2) +{ + PolygonArrayEntry* poly1 = &polygonArray[*(const unsigned int*)p1]; + PolygonArrayEntry* poly2 = &polygonArray[*(const unsigned int*)p2]; + int diff; + INT64 diff64; + + 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; + + diff = poly1->texNum - poly2->texNum; + 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; + 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) + { + *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; + } + + // 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) + { + // 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); + } + // 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; + boolean changeTexture = false; + GLuint nextTexture; + boolean changePolyFlags = false; + FBITFIELD nextPolyFlags; + 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; +} // -----------------+ // DrawPolygon : Render a polygon, set the texture, set render mode // -----------------+ -EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, - //FTextureInfo *pTexInfo, - FOutVector *pOutVerts, - FUINT iNumPts, - FBITFIELD PolyFlags) +EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags) { - FUINT i; - FUINT j; - - if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD)) - PolyFlags &= ~(PF_NoDepthTest|PF_Corona); - - SetBlend(PolyFlags); //TODO: inline (#pragma..) - - // If Modulated, mix the surface colour to the texture - if ((CurrentPolyFlags & PF_Modulated) && pSurf) - pglColor4ubv((GLubyte*)&pSurf->FlatColor.s); - - // 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 + if (gl_batching) { - //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; + //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)); + } - GLubyte c[4]; + 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; + } - float alpha; + // add the polygon data to the arrays - 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; + 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++; - // I dont know if this is slow or not - GLProject(cx, cy, cz, &px, &py, &pz); - //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); - //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; - //DBG_Printf("Scale factor: %f\n", scalef); - - if (scalef < 0.05f) - return; - - // GLubyte c[4]; - c[0] = pSurf->FlatColor.s.red; - c[1] = pSurf->FlatColor.s.green; - c[2] = pSurf->FlatColor.s.blue; - - alpha = byte2float[pSurf->FlatColor.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); + 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}; - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].sow); - pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); + SetBlend(PolyFlags); //TODO: inline (#pragma..) - if (PolyFlags & PF_RemoveYWrap) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // 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]; - if (PolyFlags & PF_ForceWrapX) - Clamp2D(GL_TEXTURE_WRAP_S); + 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]; - if (PolyFlags & PF_ForceWrapY) - Clamp2D(GL_TEXTURE_WRAP_T); + // 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); + } } +// Sky dome code, taken/backported from SRB2 + +typedef struct vbo_vertex_s +{ + float x, y, z; + float u, v; + unsigned char r, g, b, a; +} vbo_vertex_t; + +typedef struct +{ + int mode; + int vertexcount; + int vertexindex; + int use_texture; +} GLSkyLoopDef; + +typedef struct +{ + unsigned int id; + int rows, columns; + int loopcount; + GLSkyLoopDef *loops; + vbo_vertex_t *data; +} GLSkyVBO; + +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) + +// 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) +{ + int i, j; + int vbosize; + GLSkyVBO *vbo = &sky_vbo; + + rows = 4; + columns = 4 * gl_sky_detail; + + vbosize = 2 * rows * (columns * 2 + 2) + columns * 2; + + // Build the sky dome! Yes! + if (lasttex != skytexture) + { + // delete VBO when already exists + if (gl_ext_arb_vertex_buffer_object) + { + if (vbo->id) + pglDeleteBuffers(1, &vbo->id); + } + + 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); + + // bind VBO in order to use + pglBindBuffer(GL_ARRAY_BUFFER, vbo->id); + + // upload data to VBO + pglBufferData(GL_ARRAY_BUFFER, vbosize * sizeof(vbo->data[0]), vbo->data, GL_STATIC_DRAW); + } + } + + // bind VBO in order to use + if (gl_ext_arb_vertex_buffer_object) + pglBindBuffer(GL_ARRAY_BUFFER, vbo->id); + + // 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); + + // activate color arrays + pglEnableClientState(GL_COLOR_ARRAY); + + // set transforms + pglScalef(1.0f, (float)texh / 230.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++) + { + GLSkyLoopDef *loop = &vbo->loops[i]; + + if (j == 0 ? loop->use_texture : !loop->use_texture) + continue; + + pglDrawArrays(loop->mode, loop->vertexindex, loop->vertexcount); + } + } + + pglScalef(1.0f, 1.0f, 1.0f); + pglColor4ubv(white); + + // bind with 0, so, switch back to normal pointer operation + if (gl_ext_arb_vertex_buffer_object) + pglBindBuffer(GL_ARRAY_BUFFER, 0); + + // deactivate color array + 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); +} // ========================================================================== // @@ -1413,56 +2599,16 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) { switch (IdState) { - -#if 0 - case 77: - { - //08/01/00: Hurdler this is a test for mirror - if (!Value) - ClearBuffer(false, true, 0); // clear depth buffer - break; - } -#endif - - case HWD_SET_FOG_COLOR: - { - GLfloat fogcolor[4]; - - fogcolor[0] = byte2float[((Value>>16)&0xff)]; - fogcolor[1] = byte2float[((Value>>8)&0xff)]; - fogcolor[2] = byte2float[((Value)&0xff)]; - fogcolor[3] = 0x0; - pglFogfv(GL_FOG_COLOR, fogcolor); - break; - } - case HWD_SET_FOG_DENSITY: - pglFogf(GL_FOG_DENSITY, Value*1200/(500*1000000.0f)); - break; - - case HWD_SET_FOG_MODE: - if (Value) + case HWD_SET_SHADERS: + switch (Value) { - pglEnable(GL_FOG); - // experimental code - /* - switch (Value) - { - case 1: - glFogi(GL_FOG_MODE, GL_LINEAR); - pglFogf(GL_FOG_START, -1000.0f); - pglFogf(GL_FOG_END, 2000.0f); - break; - case 2: - glFogi(GL_FOG_MODE, GL_EXP); - break; - case 3: - glFogi(GL_FOG_MODE, GL_EXP2); - break; - } - */ + case 1: + gl_allowshaders = true; + break; + default: + gl_allowshaders = false; + break; } - else - pglDisable(GL_FOG); break; case HWD_SET_TEXTUREFILTERMODE: @@ -1632,6 +2778,10 @@ static void CreateModelVBO(mesh_t *mesh, mdlframe_t *frame) pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); free(buffer); + + // Don't leave the array buffer bound to the model, + // since this is called mid-frame + pglBindBuffer(GL_ARRAY_BUFFER, 0); } static void CreateModelVBOTiny(mesh_t *mesh, tinyframe_t *frame) @@ -1673,6 +2823,10 @@ static void CreateModelVBOTiny(mesh_t *mesh, tinyframe_t *frame) pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); free(buffer); + + // Don't leave the array buffer bound to the model, + // since this is called mid-frame + pglBindBuffer(GL_ARRAY_BUFFER, 0); } EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) @@ -1709,12 +2863,13 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) } } -#define BUFFER_OFFSET(i) ((char*)NULL + (i)) +#define BUFFER_OFFSET(i) ((char*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) { - GLfloat ambient[4]; - GLfloat diffuse[4]; + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; float pol = 0.0f; float scalex, scaley, scalez; @@ -1723,9 +2878,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 int i; - // Because Otherwise, scaling the screen negatively vertically breaks the lighting - GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; - // Affect input model scaling scale *= 0.5f; scalex = scale; @@ -1745,24 +2897,29 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pol = 0.0f; } - if (color) - { - ambient[0] = (color[0]/255.0f); - ambient[1] = (color[1]/255.0f); - ambient[2] = (color[2]/255.0f); - ambient[3] = (color[3]/255.0f); - diffuse[0] = (color[0]/255.0f); - diffuse[1] = (color[1]/255.0f); - diffuse[2] = (color[2]/255.0f); - diffuse[3] = (color[3]/255.0f); + poly.red = byte2float[Surface->PolyColor.s.red]; + poly.green = byte2float[Surface->PolyColor.s.green]; + poly.blue = byte2float[Surface->PolyColor.s.blue]; + poly.alpha = byte2float[Surface->PolyColor.s.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; - } + if (poly.alpha < 1) + SetBlend(PF_Translucent|PF_Modulated); + else + SetBlend(PF_Masked|PF_Modulated|PF_Occlude); + + pglColor4ubv((GLubyte*)&Surface->PolyColor.s); + + 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); pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); @@ -1782,33 +2939,12 @@ 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 - { pglCullFace(GL_FRONT); - } else - { pglCullFace(GL_BACK); - } #endif - pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); - - pglShadeModel(GL_SMOOTH); - if (color) - { -#ifdef GL_LIGHT_MODEL_AMBIENT - pglEnable(GL_LIGHTING); - pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); - pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); -#endif - if (color[3] < 255) - SetBlend(PF_Translucent|PF_Modulated|PF_Clip); - else - SetBlend(PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); - } - pglPushMatrix(); // should be the same as glLoadIdentity - //Hurdler: now it seems to work pglTranslatef(pos->x, pos->z, pos->y); if (flipped) scaley = -scaley; @@ -1845,7 +2981,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 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); } @@ -1853,13 +2988,12 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 { short *vertPtr; char *normPtr; - int j; + int j = 0; // Dangit, I soooo want to do this in a GLSL shader... AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); vertPtr = vertTinyBuffer; normPtr = normTinyBuffer; - j = 0; for (j = 0; j < mesh->numVertices * 3; j++) { @@ -1885,19 +3019,12 @@ 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. -/* 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);*/ - 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); - // No tinyframes, no mesh indices - //pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); pglBindBuffer(GL_ARRAY_BUFFER, 0); } else @@ -1910,7 +3037,6 @@ 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++) { @@ -1930,19 +3056,16 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglDisableClientState(GL_NORMAL_ARRAY); pglPopMatrix(); // should be the same as glLoadIdentity - if (color) - pglDisable(GL_LIGHTING); - pglShadeModel(GL_FLAT); pglDisable(GL_CULL_FACE); pglDisable(GL_NORMALIZE); } // -----------------+ -// HWRAPI DrawMD2 : Draw an MD2 model with glcommands +// 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, UINT8 *color) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, color); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface); } // -----------------+ @@ -1952,10 +3075,12 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) { static boolean special_splitscreen; GLdouble used_fov; + boolean shearing = false; 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)); @@ -1970,7 +3095,8 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) else pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez); - pglRotatef(stransform->anglex , 1.0f, 0.0f, 0.0f); + pglMatrixMode(GL_MODELVIEW); + 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); @@ -1985,9 +3111,19 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); + + // jimita 14042019 + // Simulate Software's y-shearing + // 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); + } + if (special_splitscreen) { - used_fov = atan(tan(used_fov*M_PIl/360.0l)*0.8l)*360/M_PIl; + used_fov = atan(tan(used_fov*M_PIl/360)*0.8)*360/M_PIl; GLPerspective((GLfloat)used_fov, 2*ASPECT_RATIO); } else @@ -2011,11 +3147,6 @@ EXPORT INT32 HWRAPI(GetTextureUsed) (void) return res; } -EXPORT INT32 HWRAPI(GetRenderVersion) (void) -{ - return VERSION; -} - EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) { INT32 x, y; @@ -2031,7 +3162,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) 16.0f, -16.0f, 6.0f }; - // Use a power of two texture, dammit + // Use a power of two texture if(screen_width <= 1024) texsize = 1024; if(screen_width <= 512) @@ -2044,8 +3175,6 @@ 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); @@ -2053,6 +3182,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglVertexPointer(3, GL_FLOAT, 0, blackBack); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); for(x=0;x0; i--) { - const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); + char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); size_t j = 0; INT32 linescount = 0; @@ -1524,6 +1524,8 @@ static void HU_drawMiniChat(void) dy = 0; dx = 0; msglines += linescount+1; + if (msg) + Z_Free(msg); } y = chaty - charheight*(msglines+1); @@ -1550,7 +1552,7 @@ static void HU_drawMiniChat(void) INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. size_t j = 0; - const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. UINT8 *colormap = NULL; while(msg[j]) // iterate through msg @@ -1596,6 +1598,8 @@ static void HU_drawMiniChat(void) } dy += charheight; dx = 0; + if (msg) + Z_Free(msg); } // decrement addy and make that shit smooth: @@ -1651,7 +1655,7 @@ static void HU_drawChatLog(INT32 offset) { INT32 clrflag = 0; INT32 j = 0; - const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it. + char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it. UINT8 *colormap = NULL; while(msg[j]) // iterate through msg { @@ -1691,6 +1695,8 @@ static void HU_drawChatLog(INT32 offset) } dy += charheight; dx = 0; + if (msg) + Z_Free(msg); } diff --git a/src/i_addrinfo.c b/src/i_addrinfo.c index 20766275..42d4b892 100644 --- a/src/i_addrinfo.c +++ b/src/i_addrinfo.c @@ -74,10 +74,10 @@ static int inet_aton(const char *cp, struct in_addr *addr) #ifdef USE_WINSOCK2 static HMODULE ipv6dll = NULL; -typedef int (WSAAPI *p_getaddrinfo) (const char *node, const char *service, - const struct my_addrinfo *hints, - struct my_addrinfo **res); -typedef void (WSAAPI *p_freeaddrinfo) (struct my_addrinfo *res); +typedef int (WSAAPI *p_getaddrinfo) (const char *, const char *, + const struct my_addrinfo *, + struct my_addrinfo **); +typedef void (WSAAPI *p_freeaddrinfo) (struct my_addrinfo *); static p_getaddrinfo WS_getaddrinfo = NULL; static p_freeaddrinfo WS_freeaddrinfo = NULL; @@ -86,10 +86,10 @@ static HMODULE WS_getfunctions(HMODULE tmp) { if (tmp != NULL) { - WS_getaddrinfo = (p_getaddrinfo)((void *)GetProcAddress(tmp, "getaddrinfo")); + WS_getaddrinfo = (p_getaddrinfo)(LPVOID)GetProcAddress(tmp, "getaddrinfo"); if (WS_getaddrinfo == NULL) return NULL; - WS_freeaddrinfo = (p_freeaddrinfo)((void *)GetProcAddress(tmp, "freeaddrinfo")); + WS_freeaddrinfo = (p_freeaddrinfo)(LPVOID)GetProcAddress(tmp, "freeaddrinfo"); if (WS_freeaddrinfo == NULL) { WS_getaddrinfo = NULL; diff --git a/src/i_system.h b/src/i_system.h index d1708fe5..3e589c69 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -226,10 +226,6 @@ void I_StartupMouse(void); */ void I_StartupMouse2(void); -/** \brief keyboard startup, shutdown, handler -*/ -void I_StartupKeyboard(void); - /** \brief setup timer irq and user timer routine. */ void I_StartupTimer(void); diff --git a/src/info.c b/src/info.c index d609bf55..d639b617 100644 --- a/src/info.c +++ b/src/info.c @@ -20,9 +20,6 @@ #include "z_zone.h" #include "d_player.h" #include "lzf.h" -#ifdef HWRENDER -#include "hardware/hw_light.h" -#endif // 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! char sprnames[NUMSPRITES + 1][5] = @@ -20101,7 +20098,7 @@ void P_PatchInfoTables(void) char *tempname; #if NUMSPRITEFREESLOTS > 1000 -"Update P_PatchInfoTables, you big dumb head" +#error "Update P_PatchInfoTables, you big dumb head" #endif // empty out free slots @@ -20113,9 +20110,6 @@ void P_PatchInfoTables(void) tempname[2] = (char)('0' + (char)(((i-SPR_FIRSTFREESLOT+1)/10)%10)); tempname[3] = (char)('0' + (char)((i-SPR_FIRSTFREESLOT+1)%10)); tempname[4] = '\0'; -#ifdef HWRENDER - t_lspr[i] = &lspr[NOLIGHT]; -#endif } sprnames[i][0] = '\0'; // i == NUMSPRITES memset(&states[S_FIRSTFREESLOT], 0, sizeof (state_t) * NUMSTATEFREESLOTS); diff --git a/src/info.h b/src/info.h index 0e23a07c..a00b53d0 100644 --- a/src/info.h +++ b/src/info.h @@ -226,7 +226,7 @@ void A_NapalmScatter(); void A_SpawnFreshCopy(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 -#define NUMMOBJFREESLOTS 256 +#define NUMMOBJFREESLOTS 512 #define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS #define NUMSTATEFREESLOTS (NUMMOBJFREESLOTS*8) @@ -4301,7 +4301,7 @@ typedef enum mobj_type // Castle Eggman Scenery MT_CHAIN, // CEZ Chain - MT_FLAME, // Flame (has corona) + MT_FLAME, // Flame MT_EGGSTATUE, // Eggman Statue MT_MACEPOINT, // Mace rotation point MT_SWINGMACEPOINT, // Mace swinging point diff --git a/src/k_kart.c b/src/k_kart.c index 10d772ba..cc5504bb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -409,7 +409,7 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { // 0.0722 to blue // (See this same define in hw_md2.c!) #define SETBRIGHTNESS(brightness,r,g,b) \ - brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) /** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power @@ -1062,7 +1062,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) } // This makes the roulette produce the random noises. - if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player)) + if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player) && !demo.freecam) { #define PLAYROULETTESND S_StartSound(NULL, sfx_itrol1 + ((player->kartstuff[k_itemroulette] / 3) % 8)) for (i = 0; i <= splitscreen; i++) @@ -1096,7 +1096,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) //player->kartstuff[k_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsDisplayPlayer(player)) + if (P_IsDisplayPlayer(player) && !demo.freecam) S_StartSound(NULL, sfx_itrole); return; } @@ -1109,7 +1109,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemblinkmode] = 2; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsDisplayPlayer(player)) + if (P_IsDisplayPlayer(player) && !demo.freecam) S_StartSound(NULL, sfx_dbgsal); return; } @@ -1141,7 +1141,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemamount] = 1; } - if (P_IsDisplayPlayer(player)) + if (P_IsDisplayPlayer(player) && !demo.freecam) S_StartSound(NULL, ((player->kartstuff[k_roulettetype] == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf))); player->kartstuff[k_itemblink] = TICRATE; @@ -3159,11 +3159,11 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (dir == -1) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x06000000, 0, PROJSPEED/4); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x03000000, 0, PROJSPEED/4); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/4); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x03000000, 0, PROJSPEED/4); - K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x06000000, 0, PROJSPEED/4); + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x06000000, 0, PROJSPEED/16); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x03000000, 0, PROJSPEED/16); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/16); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x03000000, 0, PROJSPEED/16); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x06000000, 0, PROJSPEED/16); } else { @@ -3180,7 +3180,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (dir == -1 && mapthing != MT_SPB) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/2); + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/8); } else { @@ -8750,6 +8750,7 @@ void K_drawKartHUD(void) { boolean isfreeplay = false; boolean battlefullscreen = false; + boolean freecam = demo.freecam; //disable some hud elements w/ freecam UINT8 i; // Define the X and Y for each drawn object @@ -8759,7 +8760,7 @@ void K_drawKartHUD(void) // Draw that fun first person HUD! Drawn ASAP so it looks more "real". for (i = 0; i <= splitscreen; i++) { - if (stplyr == &players[displayplayers[i]] && !camera[i].chase) + if (stplyr == &players[displayplayers[i]] && !camera[i].chase && !freecam) K_drawKartFirstPerson(); } @@ -8780,8 +8781,11 @@ void K_drawKartHUD(void) if (!demo.title && (!battlefullscreen || splitscreen)) { // Draw the CHECK indicator before the other items, so it's overlapped by everything else - if (cv_kartcheck.value && !splitscreen && !players[displayplayers[0]].exiting) - K_drawKartPlayerCheck(); +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_check)) // delete lua when? +#endif + if (cv_kartcheck.value && !splitscreen && !players[displayplayers[0]].exiting && !freecam) + K_drawKartPlayerCheck(); // Draw WANTED status if (G_BattleGametype()) @@ -8801,7 +8805,7 @@ void K_drawKartHUD(void) } } - if (battlefullscreen) + if (battlefullscreen && !freecam) { #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_battlefullscreen)) @@ -8812,7 +8816,7 @@ void K_drawKartHUD(void) // Draw the item window #ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_item)) + if (LUA_HudEnabled(hud_item) && !freecam) #endif K_drawKartItem(); @@ -8835,7 +8839,7 @@ void K_drawKartHUD(void) } } - if (!stplyr->spectator) // Bottom of the screen elements, don't need in spectate mode + if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode { if (demo.title) // Draw title logo instead in demo.titles { @@ -8910,9 +8914,9 @@ void K_drawKartHUD(void) if (leveltime >= starttime-(3*TICRATE) && leveltime < starttime+TICRATE) K_drawKartStartCountdown(); - else if (countdown && (!splitscreen || !stplyr->exiting)) + else if (racecountdown && (!splitscreen || !stplyr->exiting)) { - char *countstr = va("%d", countdown/TICRATE); + char *countstr = va("%d", racecountdown/TICRATE); if (splitscreen > 1) V_DrawCenteredString(BASEVIDWIDTH/4, LAPS_Y+1, K_calcSplitFlags(0), countstr); @@ -8924,7 +8928,7 @@ void K_drawKartHUD(void) } // Race overlays - if (G_RaceGametype()) + if (G_RaceGametype() && !freecam) { if (stplyr->exiting) K_drawKartFinish(); @@ -8932,7 +8936,7 @@ void K_drawKartHUD(void) K_drawLapStartAnim(); } - if (modeattacking) // everything after here is MP and debug only + if (modeattacking || freecam) // everything after here is MP and debug only return; if (G_BattleGametype() && !splitscreen && (stplyr->kartstuff[k_yougotem] % 2)) // * YOU GOT EM * diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6700d5af..d7292cd6 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -774,11 +774,14 @@ static int lib_pRestoreMusic(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - if (P_IsLocalPlayer(player)) + if (!player || P_IsLocalPlayer(player)) + { P_RestoreMusic(player); - return 0; + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; } static int lib_pSpawnShieldOrb(lua_State *L) @@ -1867,8 +1870,13 @@ static int lib_sChangeMusic(lua_State *L) fadeinms = (UINT32)luaL_optinteger(L, 7, 0); if (!player || P_IsLocalPlayer(player)) + { S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms); - return 0; + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; } static int lib_sSpeedMusic(lua_State *L) @@ -1884,8 +1892,230 @@ static int lib_sSpeedMusic(lua_State *L) return LUA_ErrInvalid(L, "player_t"); } if (!player || P_IsLocalPlayer(player)) - S_SpeedMusic(speed); - return 0; + lua_pushboolean(L, S_SpeedMusic(speed)); + else + lua_pushnil(L); + return 1; +} + +static int lib_sMusicType(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, S_MusicType()); + else + lua_pushnil(L); + return 1; +} + +static int lib_sMusicPlaying(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_pushboolean(L, S_MusicPlaying()); + else + lua_pushnil(L); + return 1; +} + +static int lib_sMusicPaused(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_pushboolean(L, S_MusicPaused()); + else + lua_pushnil(L); + return 1; +} + +static int lib_sMusicName(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_pushstring(L, S_MusicName()); + else + lua_pushnil(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; + char music_compat_name[7]; + UINT16 music_flags = 0; + NOHUD + if (lua_isnumber(L, 1)) + { + music_num = (UINT32)luaL_checkinteger(L, 1); + music_flags = (UINT16)(music_num & 0x0000FFFF); + if (music_flags && music_flags <= 1035) + snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags)); + else if (music_flags && music_flags <= 1050) + strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7); + else + music_compat_name[0] = 0; // becomes empty string + music_compat_name[6] = 0; + music_name = (const char *)&music_compat_name; + } + else + { + music_num = 0; + music_name = luaL_checkstring(L, 1); + } +#else + 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); + return 1; +} + +static int lib_sSetMusicLoopPoint(lua_State *L) +{ + UINT32 looppoint = (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_SetMusicLoopPoint(looppoint)); + else + lua_pushnil(L); + return 1; +} + +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); + return 1; +} + +static int lib_sSetMusicPosition(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); + return 1; +} + +static int lib_sGetMusicPosition(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_GetMusicPosition()); + else + lua_pushnil(L); + return 1; } static int lib_sStopMusic(lua_State *L) @@ -1899,8 +2129,53 @@ static int lib_sStopMusic(lua_State *L) return LUA_ErrInvalid(L, "player_t"); } if (!player || P_IsLocalPlayer(player)) + { S_StopMusic(); - return 0; + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; +} + +static int lib_sPauseMusic(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)) + { + S_PauseAudio(); + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; +} + +static int lib_sResumeMusic(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)) + { + S_ResumeAudio(); + lua_pushboolean(L, true); + } + else + lua_pushnil(L); + return 1; } static int lib_sSetInternalMusicVolume(lua_State *L) @@ -2641,6 +2916,41 @@ 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}, @@ -2802,6 +3112,19 @@ static luaL_Reg lib[] = { {"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}, + {"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint}, + {"S_SetMusicPosition",lib_sSetMusicPosition}, + {"S_GetMusicPosition",lib_sGetMusicPosition}, + {"S_PauseMusic",lib_sPauseMusic}, + {"S_ResumeMusic",lib_sResumeMusic}, {"S_StopMusic",lib_sStopMusic}, {"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume}, {"S_StopFadingMusic",lib_sStopFadingMusic}, @@ -2868,6 +3191,10 @@ 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} }; diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 299870e0..0c73459c 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -413,6 +413,30 @@ static int lib_cvRegisterVar(lua_State *L) return 1; } +// For some reason I couldn't cherry pick this. +// Credits for this function go to james. All hail birb. -Lat' + +static int lib_cvFindVar(lua_State *L) +{ + consvar_t *cv; + if (( cv = CV_FindVar(luaL_checkstring(L,1)) )) + { + lua_settop(L,1);/* We only want one argument in the stack. */ + lua_pushlightuserdata(L, cv);/* Now the second value on stack. */ + luaL_getmetatable(L, META_CVAR); + /* + The metatable is the last value on the stack, so this + applies it to the second value, which is the cvar. + */ + lua_setmetatable(L,2); + lua_pushvalue(L,2); + return 1; + } + else + return 0; +} + + // CONS_Printf for a single player // Use 'print' in baselib for a global message. static int lib_consPrintf(lua_State *L) @@ -452,6 +476,7 @@ static luaL_Reg lib[] = { {"COM_BufInsertText", lib_comBufInsertText}, {"CV_RegisterVar", lib_cvRegisterVar}, {"CONS_Printf", lib_consPrintf}, + {"CV_FindVar", lib_cvFindVar}, {NULL, NULL} }; diff --git a/src/lua_hook.h b/src/lua_hook.h index e61acdf1..6af3941f 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -44,6 +44,7 @@ enum hook { hook_HurtMsg, hook_PlayerSpawn, hook_PlayerQuit, + hook_MusicChange, hook_ShouldSpin, //SRB2KART hook_ShouldExplode, //SRB2KART hook_ShouldSquish, //SRB2KART @@ -52,6 +53,7 @@ enum hook { hook_PlayerSquish, //SRB2KART hook_PlayerCmd, //SRB2KART hook_IntermissionThinker, //SRB2KART + hook_VoteThinker, //SRB2KART hook_MAX // last hook }; @@ -89,6 +91,8 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute); boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // 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 +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? @@ -101,5 +105,6 @@ boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); 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 #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index c15d13a0..41a436e0 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -55,6 +55,7 @@ const char *const hookNames[hook_MAX+1] = { "HurtMsg", "PlayerSpawn", "PlayerQuit", + "MusicChange", "ShouldSpin", "ShouldExplode", "ShouldSquish", @@ -63,6 +64,7 @@ const char *const hookNames[hook_MAX+1] = { "PlayerSquish", "PlayerCmd", "IntermissionThinker", + "VoteThinker", NULL }; @@ -442,6 +444,27 @@ void LUAh_IntermissionThinker(void) } } +// Hook for Y_VoteTicker +void LUAh_VoteThinker(void) +{ + hook_p hookp; + if (!gL || !(hooksAvailable[hook_VoteThinker/8] & (1<<(hook_VoteThinker%8)))) + return; + + for (hookp = roothook; hookp; hookp = hookp->next) + if (hookp->type == hook_VoteThinker) + { + 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; + } + } +} + // Hook for mobj collisions UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) @@ -1191,6 +1214,65 @@ void LUAh_PlayerQuit(player_t *plr, int reason) 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) { diff --git a/src/lua_hud.h b/src/lua_hud.h index 88d7fd6b..960195cd 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -19,6 +19,7 @@ enum hud { hud_minimap, hud_item, hud_position, + hud_check, // "CHECK" f-zero indicator hud_minirankings, // Rankings to the left hud_battlebumpers, // mini rankings battle bumpers. hud_battlefullscreen, // battle huge text (WAIT, WIN, LOSE ...) + karma comeback time diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 22c89a23..22e98315 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -46,6 +46,7 @@ static const char *const hud_disable_options[] = { "minimap", "item", "position", + "check", // "CHECK" f-zero indicator "minirankings", // Gametype rankings to the left "battlerankingsbumpers", // bumper drawer for battle. Useful if you want to make a custom battle gamemode without bumpers being involved. "battlefullscreen", // battlefullscreen func (WAIT, ATTACK OR PROTECT ...) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 3cca1f91..d9766513 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -81,6 +81,88 @@ static int lib_lenPlayer(lua_State *L) return 1; } +// Same deal as the three functions above but for displayplayers + +static int lib_iterateDisplayplayers(lua_State *L) +{ + INT32 i = -1; + INT32 temp = -1; + INT32 iter = 0; + + if (lua_gettop(L) < 2) + { + //return luaL_error(L, "Don't call displayplayers.iterate() directly, use it as 'for player in displayplayers.iterate do end'."); + lua_pushcfunction(L, lib_iterateDisplayplayers); + return 1; + } + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + { + temp = (INT32)(*((player_t **)luaL_checkudata(L, 1, META_PLAYER)) - players); // get the player # of the last iterated player. + + // @FIXME: + // I didn't quite find a better way for this; Here, we go back to which player in displayplayers we last iterated to resume the for loop below for this new function call + // I don't understand enough about how the Lua stacks work to get this to work in possibly a single line. + // So anyone feel free to correct this! + + for (; iter < MAXSPLITSCREENPLAYERS; iter++) + { + if (displayplayers[iter] == temp) + { + i = iter; + break; + } + } + } + + for (i++; i < MAXSPLITSCREENPLAYERS; i++) + { + if (!playeringame[displayplayers[i]] || i > splitscreen) + return 0; // Stop! There are no more players for us to go through. There will never be a player gap in displayplayers. + + if (!players[displayplayers[i]].mo) + continue; + LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER); + lua_pushinteger(L, i); // push this to recall what number we were on for the next function call. I suppose this also means you can retrieve the splitscreen player number with 'for p, n in displayplayers.iterate'! + return 2; + } + return 0; +} + +static int lib_getDisplayplayers(lua_State *L) +{ + const char *field; + // i -> players[i] + if (lua_type(L, 2) == LUA_TNUMBER) + { + lua_Integer i = luaL_checkinteger(L, 2); + if (i < 0 || i >= MAXSPLITSCREENPLAYERS) + return luaL_error(L, "displayplayers[] index %d out of range (0 - %d)", i, MAXSPLITSCREENPLAYERS-1); + if (!playeringame[displayplayers[i]]) + return 0; + if (!players[displayplayers[i]].mo) + return 0; + LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER); + return 1; + } + + field = luaL_checkstring(L, 2); + if (fastcmp(field,"iterate")) + { + lua_pushcfunction(L, lib_iterateDisplayplayers); + return 1; + } + return 0; +} + +// #displayplayers -> MAXSPLITSCREENPLAYERS +static int lib_lenDisplayplayers(lua_State *L) +{ + lua_pushinteger(L, MAXSPLITSCREENPLAYERS); + return 1; +} + static int player_get(lua_State *L) { player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -777,6 +859,18 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_setmetatable(L, -2); lua_setglobal(L, "players"); + + // push displayplayers in the same fashion + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getDisplayplayers); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_lenDisplayplayers); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "displayplayers"); + return 0; } diff --git a/src/lua_script.c b/src/lua_script.c index 28f02ca3..6961f2e9 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -112,7 +112,7 @@ static int noglobals(lua_State *L) // Clear and create a new Lua state, laddo! // There's SCRIPTIN to be had! -static void LUA_ClearState(void) +void LUA_ClearState(void) { lua_State *L; int i; @@ -734,6 +734,220 @@ 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) { int TABLESINDEX; @@ -790,6 +1004,63 @@ static void ArchiveExtVars(void *pointer, const char *ptype) 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) + 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); +} + static int NetArchive(lua_State *L) { int TABLESINDEX = lua_upvalueindex(1); @@ -843,6 +1114,50 @@ static void ArchiveTables(void) } } +static void ArchiveTablesDemo(void) +{ + 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); @@ -932,6 +1247,109 @@ static UINT8 UnArchiveValue(int TABLESINDEX) 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); + else + CONS_Alert(CONS_WARNING,"Couldn't read mobj_t\n"); + + return 3; // Don't set the field + + case ARCH_PLAYER: + LUA_PushUserdata(gL, &players[READUINT8(demo_p)], META_PLAYER); + break; + case ARCH_MAPTHING: + LUA_PushUserdata(gL, &mapthings[READUINT16(demo_p)], META_MAPTHING); + break; + case ARCH_VERTEX: + LUA_PushUserdata(gL, &vertexes[READUINT16(demo_p)], META_VERTEX); + break; + case ARCH_LINE: + LUA_PushUserdata(gL, &lines[READUINT16(demo_p)], META_LINE); + break; + case ARCH_SIDE: + LUA_PushUserdata(gL, &sides[READUINT16(demo_p)], META_SIDE); + break; + case ARCH_SUBSECTOR: + LUA_PushUserdata(gL, &subsectors[READUINT16(demo_p)], META_SUBSECTOR); + break; + case ARCH_SECTOR: + LUA_PushUserdata(gL, §ors[READUINT16(demo_p)], META_SECTOR); + break; +#ifdef ESLOPE + case ARCH_SLOPE: + LUA_PushUserdata(gL, P_SlopeById(READUINT16(demo_p)), META_SLOPE); + break; +#endif + case ARCH_MAPHEADER: + LUA_PushUserdata(gL, mapheaderinfo[READUINT16(demo_p)], META_MAPHEADER); + break; + case ARCH_TEND: + return 1; + } + return 0; +} + static void UnArchiveExtVars(void *pointer) { int TABLESINDEX; @@ -961,6 +1379,35 @@ 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); @@ -1002,6 +1449,38 @@ static void UnArchiveTables(void) } } +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 + 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); + } +} + void LUA_Step(void) { if (!gL) @@ -1076,6 +1555,49 @@ void LUA_UnArchive(void) 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 (!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"); + } + + 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(); + + if (gL) + lua_pop(gL, 1); // pop tables +} + // For mobj_t, player_t, etc. to take custom variables. int Lua_optoption(lua_State *L, int narg, const char *def, const char *const lst[]) diff --git a/src/lua_script.h b/src/lua_script.h index f944149d..b3ca16bc 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -38,6 +38,8 @@ void LUA_ClearExtVars(void); #endif +void LUA_ClearState(void); + void LUA_LoadLump(UINT16 wad, UINT16 lump); #ifdef LUA_ALLOW_BYTECODE void LUA_DumpFile(const char *filename); @@ -51,6 +53,10 @@ void LUA_InvalidatePlayer(player_t *player); void LUA_Step(void); void LUA_Archive(void); void LUA_UnArchive(void); + +void LUA_ArchiveDemo(void); +void LUA_UnArchiveDemo(void); + void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(const char *name); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, diff --git a/src/m_anigif.c b/src/m_anigif.c index 4e68819b..f19679ef 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -19,6 +19,10 @@ #include "v_video.h" #include "i_video.h" +#ifdef HWRENDER +#include "hardware/hw_main.h" +#endif + // GIFs are always little-endian #include "byteptr.h" @@ -452,6 +456,32 @@ const UINT8 gifframe_gchead[4] = {0x21,0xF9,0x04,0x04}; // GCE, bytes, packed by static UINT8 *gifframe_data = NULL; static size_t gifframe_size = 8192; +#ifdef HWRENDER +static void hwrconvert(void) +{ + UINT8 *linear = HWR_GetScreenshot(); + UINT8 *dest = screens[2]; + UINT8 r, g, b; + INT32 x, y; + size_t i = 0; + + InitColorLUT(); + + for (y = 0; y < vid.height; y++) + { + 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]; + } + } + + free(linear); +} +#endif + // // GIF_framewrite // writes a frame into the file. @@ -477,7 +507,12 @@ static void GIF_framewrite(void) GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith); // blit to temp screen - I_ReadScreen(movie_screen); + if (rendermode == render_soft) + I_ReadScreen(movie_screen); +#ifdef HWRENDER + else if (rendermode == render_opengl) + hwrconvert(); +#endif } else { @@ -486,7 +521,18 @@ static void GIF_framewrite(void) blith = vid.height; if (gif_frames == 0) - I_ReadScreen(movie_screen); + { + 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 + } + movie_screen = screens[0]; } @@ -575,7 +621,7 @@ static void GIF_framewrite(void) // INT32 GIF_open(const char *filename) { -#ifdef HWRENDER +#if 0 if (rendermode != render_soft) { CONS_Alert(CONS_WARNING, M_GetText("GIFs cannot be taken in non-software modes!\n")); diff --git a/src/m_fixed.c b/src/m_fixed.c index 5e789673..7241be9c 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -411,6 +411,19 @@ 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)); @@ -458,19 +471,6 @@ 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_menu.c b/src/m_menu.c index 606e3bad..24852285 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -238,7 +238,6 @@ static void M_HandleStaffReplay(INT32 choice); static void M_ReplayTimeAttack(INT32 choice); static void M_ChooseTimeAttack(INT32 choice); //static void M_ChooseNightsAttack(INT32 choice); -static void M_ModeAttackRetry(INT32 choice); static void M_ModeAttackEndGame(INT32 choice); static void M_SetGuestReplay(INT32 choice); //static void M_ChoosePlayer(INT32 choice); @@ -287,7 +286,7 @@ static void M_ResetControls(INT32 choice); // Video & Sound menu_t OP_VideoOptionsDef, OP_VideoModeDef; #ifdef HWRENDER -menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef, OP_OpenGLColorDef; +menu_t OP_OpenGLOptionsDef, OP_OpenGLColorDef; #endif menu_t OP_SoundOptionsDef; //static void M_RestartAudio(void); @@ -326,6 +325,7 @@ static void M_PlaybackFastForward(INT32 choice); static void M_PlaybackAdvance(INT32 choice); static void M_PlaybackSetViews(INT32 choice); static void M_PlaybackAdjustView(INT32 choice); +static void M_PlaybackToggleFreecam(INT32 choice); static void M_PlaybackQuit(INT32 choice); static UINT8 playback_enterheld = 0; // horrid hack to prevent holding the button from being extremely fucked @@ -353,7 +353,6 @@ static void M_DrawHUDOptions(void); static void M_DrawVideoMode(void); static void M_DrawMonitorToggles(void); #ifdef HWRENDER -static void M_OGL_DrawFogMenu(void); static void M_OGL_DrawColorMenu(void); #endif static void M_DrawMPMainMenu(void); @@ -379,9 +378,6 @@ static void M_HandleLevelStats(INT32 choice); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); -#ifdef HWRENDER -static void M_HandleFogColor(INT32 choice); -#endif static void M_HandleVideoMode(INT32 choice); static void M_HandleMonitorToggles(INT32 choice); @@ -523,26 +519,26 @@ static menuitem_t MISC_ReplayOptionsMenu[] = {IT_CVAR|IT_STRING, NULL, "Sync Check Interval", &cv_netdemosyncquality, 10}, }; +static tic_t playback_last_menu_interaction_leveltime = 0; static menuitem_t PlaybackMenu[] = { - {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu", M_SelectableClearMenus, 0}, + {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu (Esc)", M_SelectableClearMenus, 0}, - {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20}, - {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward", M_PlaybackFastForward, 52}, - {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame", M_PlaybackRewind, 20}, + {IT_CALL | IT_STRING, "M_PREW", "Rewind ([)", M_PlaybackRewind, 20}, + {IT_CALL | IT_STRING, "M_PPAUSE", "Pause (\\)", M_PlaybackPause, 36}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward (])", M_PlaybackFastForward, 52}, + {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame ([)", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52}, + {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame (])", M_PlaybackAdvance, 52}, - {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count", M_PlaybackSetViews, 72}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint", M_PlaybackAdjustView, 88}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2", M_PlaybackAdjustView, 104}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3", M_PlaybackAdjustView, 120}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4", M_PlaybackAdjustView, 136}, + {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count (- and =)", M_PlaybackSetViews, 72}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint (1)", M_PlaybackAdjustView, 88}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2 (2)", M_PlaybackAdjustView, 104}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3 (3)", M_PlaybackAdjustView, 120}, + {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4 (4)", M_PlaybackAdjustView, 136}, - //{IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 156}, - //{IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, - {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 156}, + {IT_CALL | IT_STRING, "M_PVIEWS", "Toggle Free Camera (')", M_PlaybackToggleFreecam, 156}, + {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, }; typedef enum { @@ -558,6 +554,7 @@ typedef enum playback_view2, playback_view3, playback_view4, + playback_freecamera, //playback_moreoptions, playback_quit } playback_e; @@ -584,7 +581,7 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, + {IT_STRING | IT_CALL, NULL, "Addons...", M_Addons, 8}, {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, @@ -991,10 +988,9 @@ static menuitem_t MP_MainMenu[] = static menuitem_t MP_ServerMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 0}, - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, - {IT_STRING|IT_CVAR|IT_CV_PASSWORD, NULL, "Password", &cv_dummyjoinpassword, 44}, + {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 10}, + {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 20}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 30}, {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, @@ -1251,15 +1247,13 @@ static menuitem_t OP_VideoOptionsMenu[] = {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, "Field of View", &cv_fov, 75}, {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90}, {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100}, #ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmdls, 115}, - {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 125}, - {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 135}, + {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 120}, #endif }; @@ -1278,8 +1272,6 @@ enum op_video_fps, op_video_vsync, #ifdef HWRENDER - op_video_md2, - op_video_kartman, op_video_ogl, #endif }; @@ -1292,36 +1284,19 @@ static menuitem_t OP_VideoModeMenu[] = #ifdef HWRENDER static menuitem_t OP_OpenGLOptionsMenu[] = { - {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 10}, - {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 20}, + {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, "Quality", &cv_scr_depth, 35}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 45}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 55}, -/*#ifdef _WINDOWS - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50}, -#endif -#ifdef ALAM_LIGHTING - {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 70}, -#endif*/ -}; + {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}, -#ifdef ALAM_LIGHTING -static menuitem_t OP_OpenGLLightingMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Coronas", &cv_grcoronas, 0}, - {IT_STRING|IT_CVAR, NULL, "Coronas size", &cv_grcoronasize, 10}, - {IT_STRING|IT_CVAR, NULL, "Dynamic lighting", &cv_grdynamiclighting, 20}, - {IT_STRING|IT_CVAR, NULL, "Static lighting", &cv_grstaticlighting, 30}, -}; -#endif + {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}, -static menuitem_t OP_OpenGLFogMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Fog", &cv_grfog, 10}, - {IT_STRING|IT_KEYHANDLER, NULL, "Fog Color", M_HandleFogColor, 20}, - {IT_STRING|IT_CVAR, NULL, "Fog Density", &cv_grfogdensity, 30}, - {IT_STRING|IT_CVAR, NULL, "Software Fog",&cv_grsoftwarefog,40}, + {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 130}, }; static menuitem_t OP_OpenGLColorMenu[] = @@ -1369,7 +1344,7 @@ 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, "Add-on Options...", M_AddonsOptions, 20}, + {IT_STRING | IT_CALL, NULL, "Addon Options...", M_AddonsOptions, 20}, {IT_STRING | IT_SUBMENU, NULL, "Replay Options...", &MISC_ReplayOptionsDef, 30}, {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 50}, @@ -1421,7 +1396,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 add-ons 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}, @@ -1508,7 +1483,7 @@ static menuitem_t OP_ServerOptionsMenu[] = #ifndef NONET {IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 90}, {IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 100}, - {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 110}, + {IT_STRING | IT_CVAR, NULL, "Allow Addon Downloading", &cv_downloading, 110}, {IT_STRING | IT_CVAR, NULL, "Pause Permission", &cv_pause, 120}, {IT_STRING | IT_CVAR, NULL, "Mute All Chat", &cv_mute, 130}, @@ -2085,20 +2060,6 @@ menu_t OP_MonitorToggleDef = #ifdef HWRENDER menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); -#ifdef ALAM_LIGHTING -menu_t OP_OpenGLLightingDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLLightingMenu, &OP_OpenGLOptionsDef, 60, 40); -#endif -menu_t OP_OpenGLFogDef = -{ - "M_VIDEO", - sizeof (OP_OpenGLFogMenu)/sizeof (menuitem_t), - &OP_OpenGLOptionsDef, - OP_OpenGLFogMenu, - M_OGL_DrawFogMenu, - 60, 40, - 0, - NULL -}; menu_t OP_OpenGLColorDef = { "M_VIDEO", @@ -2471,9 +2432,6 @@ static void M_NextOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop - if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) - ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; - do { if (itemOn + 1 > currentMenu->numitems - 1) @@ -2487,9 +2445,6 @@ static void M_PrevOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop - if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) - ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; - do { if (!itemOn) @@ -2774,10 +2729,8 @@ boolean M_Responder(event_t *ev) // BP: one of the more big hack i have never made if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR) { - if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING || (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING) { - if (ch == KEY_TAB && (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) - ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value ^= 1; if (shiftdown && ch >= 32 && ch <= 127) ch = shiftxform[ch]; @@ -2790,8 +2743,9 @@ boolean M_Responder(event_t *ev) routine = M_ChangeCvar; } - if (currentMenu == &PlaybackMenuDef) + if (currentMenu == &PlaybackMenuDef && !con_destlines) { + playback_last_menu_interaction_leveltime = leveltime; // Flip left/right with up/down for the playback menu, since it's a horizontal icon row. switch (ch) { @@ -2799,6 +2753,56 @@ boolean M_Responder(event_t *ev) case KEY_UPARROW: ch = KEY_RIGHTARROW; break; case KEY_RIGHTARROW: ch = KEY_DOWNARROW; break; case KEY_DOWNARROW: ch = KEY_LEFTARROW; break; + + // arbitrary keyboard shortcuts because fuck you + + case '\'': // toggle freecam + M_PlaybackToggleFreecam(0); + break; + + case ']': // ffw / advance frame (depends on if paused or not) + if (paused) + M_PlaybackAdvance(0); + else + M_PlaybackFastForward(0); + break; + + case '[': // rewind /backupframe, uses the same function + M_PlaybackRewind(0); + break; + + case '\\': // pause + M_PlaybackPause(0); + break; + + // viewpoints, an annoyance (tm) + case '-': // viewpoint minus + M_PlaybackSetViews(-1); // yeah lol. + break; + + case '=': // viewpoint plus + M_PlaybackSetViews(1); // yeah lol. + break; + + // switch viewpoints: + case '1': // viewpoint for p1 (also f12) + // maximum laziness: + if (!demo.freecam) + G_AdjustView(1, 1, true); + break; + case '2': // viewpoint for p2 + if (!demo.freecam) + G_AdjustView(2, 1, true); + break; + case '3': // viewpoint for p3 + if (!demo.freecam) + G_AdjustView(3, 1, true); + break; + case '4': // viewpoint for p4 + if (!demo.freecam) + G_AdjustView(4, 1, true); + break; + default: break; } } @@ -2853,9 +2857,9 @@ boolean M_Responder(event_t *ev) if (currentMenu == &PlaybackMenuDef) { boolean held = (boolean)playback_enterheld; - playback_enterheld = TICRATE/7; if (held) return true; + playback_enterheld = 3; } if (routine) @@ -2867,7 +2871,7 @@ boolean M_Responder(event_t *ev) if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && majormods) { S_StartSound(NULL, sfx_menu1); - M_StartMessage(M_GetText("This cannot be done with complex add-ons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); + M_StartMessage(M_GetText("This cannot be done with complex addons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); return true; } } @@ -2956,6 +2960,93 @@ boolean M_Responder(event_t *ev) return true; } +// special responder for demos +boolean M_DemoResponder(event_t *ev) +{ + + INT32 ch = -1; // cur event data + boolean eatinput = false; // :omnom: + + //should be accounted for beforehand but just to be safe... + if (!demo.playback || demo.title) + return false; + + if (noFurtherInput) + { + // Ignore input after enter/escape/other buttons + // (but still allow shift keyup so caps doesn't get stuck) + return false; + } + else if (ev->type == ev_keydown && !con_destlines) // not while the console is on please + { + ch = ev->data1; + // since this is ONLY for demos, there isn't MUCH for us to do. + // mirrored from m_responder + + switch (ch) + { + // arbitrary keyboard shortcuts because fuck you + + case '\'': // toggle freecam + M_PlaybackToggleFreecam(0); + eatinput = true; + break; + + case ']': // ffw / advance frame (depends on if paused or not) + if (paused) + M_PlaybackAdvance(0); + else + M_PlaybackFastForward(0); + eatinput = true; + break; + + case '[': // rewind /backupframe, uses the same function + M_PlaybackRewind(0); + break; + + case '\\': // pause + M_PlaybackPause(0); + eatinput = true; + break; + + // viewpoints, an annoyance (tm) + case '-': // viewpoint minus + M_PlaybackSetViews(-1); // yeah lol. + eatinput = true; + break; + + case '=': // viewpoint plus + M_PlaybackSetViews(1); // yeah lol. + eatinput = true; + break; + + // switch viewpoints: + case '1': // viewpoint for p1 (also f12) + // maximum laziness: + if (!demo.freecam) + G_AdjustView(1, 1, true); + break; + case '2': // viewpoint for p2 + if (!demo.freecam) + G_AdjustView(2, 1, true); + break; + case '3': // viewpoint for p3 + if (!demo.freecam) + G_AdjustView(3, 1, true); + break; + case '4': // viewpoint for p4 + if (!demo.freecam) + G_AdjustView(4, 1, true); + break; + + default: break; + } + + } + return eatinput; +} + + // // M_Drawer // Called after the view has been rendered, @@ -3027,6 +3118,7 @@ void M_StartControlPanel(void) if (demo.playback) { currentMenu = &PlaybackMenuDef; + playback_last_menu_interaction_leveltime = leveltime; } else if (!Playing()) { @@ -3379,9 +3471,7 @@ void M_Init(void) #ifdef HWRENDER // Permanently hide some options based on render mode if (rendermode == render_soft) - OP_VideoOptionsMenu[op_video_ogl].status = - OP_VideoOptionsMenu[op_video_kartman].status = - OP_VideoOptionsMenu[op_video_md2] .status = IT_DISABLED; + OP_VideoOptionsMenu[op_video_ogl].status = IT_DISABLED; #endif #ifndef NONET @@ -3765,8 +3855,6 @@ static void M_DrawGenericMenu(void) case IT_CVAR: { consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; - char asterisks[MAXSTRINGLENGTH+1]; - size_t sl; switch (currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: @@ -3774,27 +3862,6 @@ static void M_DrawGenericMenu(void) case IT_CV_NOPRINT: // color use this case IT_CV_INVISSLIDER: // monitor toggles use this break; - case IT_CV_PASSWORD: - if (i == itemOn) - { - V_DrawRightAlignedThinString(x + MAXSTRINGLENGTH*8 + 10, y, V_ALLOWLOWERCASE, va(M_GetText("Tab: %s password"), cv->value ? "hide" : "show")); - } - - if (!cv->value || i != itemOn) - { - sl = strlen(cv->string); - memset(asterisks, '*', sl); - memset(asterisks + sl, 0, MAXSTRINGLENGTH+1-sl); - - M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); - V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, asterisks); - if (skullAnimCounter < 4 && i == itemOn) - V_DrawCharacter(x + 8 + V_StringWidth(asterisks, 0), y + 12, - '_' | 0x80, false); - y += 16; - break; - } - /* fallthru */ case IT_CV_STRING: M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string); @@ -4546,21 +4613,11 @@ static void M_StopMessage(INT32 choice) // You can even put multiple images in one menu! static void M_DrawImageDef(void) { - // this is probably what the V_DrawFixedPatch screen-fill bullshit was for, right - //V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); -- never mind, screen fade - - // Grr. Need to autodetect for pic_ts. - pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); - if (!pictest->zero) - V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text)); + patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); + if (patch->width <= BASEVIDWIDTH) + V_DrawScaledPatch(0,0,0,patch); else - { - patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); - if (patch->height <= BASEVIDHEIGHT) - V_DrawScaledPatch(0,0,0,patch); - else - V_DrawSmallScaledPatch(0,0,0,patch); - } + V_DrawSmallScaledPatch(0,0,0,patch); if (currentMenu->menuitems[itemOn].alphaKey) { @@ -4630,8 +4687,8 @@ static void M_AddonsOptions(INT32 choice) M_SetupNextMenu(&OP_AddonsOptionsDef); } -#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!" -#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!" +#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make addons!" +#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make addons!" static void M_Addons(INT32 choice) { @@ -4807,7 +4864,7 @@ static boolean M_AddonsRefresh(void) { S_StartSound(NULL, sfx_s26d); if (refreshdirmenu & REFRESHDIR_MAX) - message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you wish to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + message = va("%c%s\x80\nMaximum number of addons reached.\nA file could not be loaded.\nIf you wish to play with this addon, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); else message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); } @@ -4819,7 +4876,7 @@ static boolean M_AddonsRefresh(void) else if (majormods && !prevmajormods) { S_StartSound(NULL, sfx_s221); - message = va("%c%s\x80\nGameplay has now been modified.\nIf you wish to play Record Attack mode, restart the game to clear existing add-ons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); + message = va("%c%s\x80\nGameplay has now been modified.\nIf you wish to play Record Attack mode, restart the game to clear existing addons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); prevmajormods = majormods; } @@ -5236,6 +5293,7 @@ void M_ReplayHut(INT32 choice) G_SetGamestate(GS_TIMEATTACK); demo.rewinding = false; + CL_ClearRewinds(); S_ChangeMusicInternal("replst", true); } @@ -5248,7 +5306,8 @@ static void M_HandleReplayHutList(INT32 choice) if (dir_on[menudepthleft]) dir_on[menudepthleft]--; else - M_PrevOpt(); + return; + //M_PrevOpt(); S_StartSound(NULL, sfx_menu1); replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; @@ -5258,7 +5317,8 @@ static void M_HandleReplayHutList(INT32 choice) if (dir_on[menudepthleft] < sizedirmenu-1) dir_on[menudepthleft]++; else - itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item + return; + //itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item S_StartSound(NULL, sfx_menu1); replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; @@ -5711,7 +5771,7 @@ static void M_DrawReplayStartMenu(void) case DFILE_ERROR_NOTLOADED: case DFILE_ERROR_INCOMPLETEOUTOFORDER: - warning = "Loading addons will mark your game as modified, and record attack may be unavailable.\nYou can watch without loading addons, but desyncs may occur."; + warning = "Loading addons will mark your game as modified, and Record Attack may be unavailable.\nYou can watch without loading addons, but desyncs may occur."; break; case DFILE_ERROR_EXTRAFILES: @@ -5765,6 +5825,11 @@ static void M_DrawPlaybackMenu(void) INT16 i; patch_t *icon; UINT8 *activemap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GOLD, GTC_MENUCACHE); + UINT32 transmap = max(0, (INT32)(leveltime - playback_last_menu_interaction_leveltime - 4*TICRATE)) / 5; + transmap = min(8, transmap) << V_ALPHASHIFT; + + if (leveltime - playback_last_menu_interaction_leveltime >= 6*TICRATE) + playback_last_menu_interaction_leveltime = leveltime - 6*TICRATE; // Toggle items if (paused && !demo.rewinding) @@ -5788,13 +5853,10 @@ static void M_DrawPlaybackMenu(void) { for (i = playback_viewcount; i <= playback_view4; i++) PlaybackMenu[i].status = IT_DISABLED; + PlaybackMenu[playback_freecamera].alphaKey = 72; + PlaybackMenu[playback_quit].alphaKey = 88; - //PlaybackMenu[playback_moreoptions].alphaKey = 72; - //PlaybackMenu[playback_quit].alphaKey = 88; - PlaybackMenu[playback_quit].alphaKey = 72; - - //currentMenu->x = BASEVIDWIDTH/2 - 52; - currentMenu->x = BASEVIDWIDTH/2 - 44; + currentMenu->x = BASEVIDWIDTH/2 - 52; } else { @@ -5805,11 +5867,8 @@ static void M_DrawPlaybackMenu(void) for (i = splitscreen+1; i < 4; i++) PlaybackMenu[playback_view1+i].status = IT_DISABLED; - //PlaybackMenu[playback_moreoptions].alphaKey = 156; - //PlaybackMenu[playback_quit].alphaKey = 172; - PlaybackMenu[playback_quit].alphaKey = 156; - - //currentMenu->x = BASEVIDWIDTH/2 - 94; + PlaybackMenu[playback_freecamera].alphaKey = 156; + PlaybackMenu[playback_quit].alphaKey = 172; currentMenu->x = BASEVIDWIDTH/2 - 88; } @@ -5846,16 +5905,16 @@ static void M_DrawPlaybackMenu(void) icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp if ((i == playback_fastforward && cv_playbackspeed.value > 1) || (i == playback_rewind && demo.rewinding)) - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, transmap|V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); else - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap); + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, transmap|V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap); if (i == itemOn) { V_DrawCharacter(currentMenu->x + currentMenu->menuitems[i].alphaKey + 4, currentMenu->y + 14, - '\x1A' | V_SNAPTOTOP|highlightflags, false); + '\x1A' | transmap|V_SNAPTOTOP|highlightflags, false); - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_SNAPTOTOP|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, transmap|V_SNAPTOTOP|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS) { @@ -5863,11 +5922,11 @@ static void M_DrawPlaybackMenu(void) if (!(i == playback_viewcount && splitscreen == 3)) V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 28 - (skullAnimCounter/5), - '\x1A' | V_SNAPTOTOP|highlightflags, false); // up arrow + '\x1A' | transmap|V_SNAPTOTOP|highlightflags, false); // up arrow if (!(i == playback_viewcount && splitscreen == 0)) V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 48 + (skullAnimCounter/5), - '\x1B' | V_SNAPTOTOP|highlightflags, false); // down arrow + '\x1B' | transmap|V_SNAPTOTOP|highlightflags, false); // down arrow switch (i) { @@ -5886,7 +5945,7 @@ static void M_DrawPlaybackMenu(void) continue; } - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, V_SNAPTOTOP|V_ALLOWLOWERCASE|highlightflags, str); + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, transmap|V_SNAPTOTOP|V_ALLOWLOWERCASE|highlightflags, str); } } } @@ -5963,6 +6022,10 @@ static void M_PlaybackAdvance(INT32 choice) static void M_PlaybackSetViews(INT32 choice) { + + if (demo.freecam) + return; // not here. + if (choice > 0) { if (splitscreen < 3) @@ -5980,6 +6043,33 @@ static void M_PlaybackAdjustView(INT32 choice) G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); } +// this one's rather tricky +static void M_PlaybackToggleFreecam(INT32 choice) +{ + (void)choice; + M_ClearMenus(true); + + // remove splitscreen: + splitscreen = 0; + R_ExecuteSetViewSize(); + + P_InitCameraCmd(); // init camera controls + if (!demo.freecam) // toggle on + { + demo.freecam = true; + democam.cam = &camera[0]; // this is rather useful + } + else // toggle off + { + demo.freecam = false; + // reset democam vars: + democam.cam = NULL; + democam.turnheld = false; + democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway + } +} + + static void M_PlaybackQuit(INT32 choice) { (void)choice; @@ -8128,7 +8218,7 @@ static void M_SetGuestReplay(INT32 choice) which(0); } -static void M_ModeAttackRetry(INT32 choice) +void M_ModeAttackRetry(INT32 choice) { (void)choice; G_CheckDemoStatus(); // Cancel recording @@ -8398,6 +8488,7 @@ static void M_DrawConnectMenu(void) V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, gt); + // display game speed for race gametypes if (serverlist[slindex].info.gametype == GT_RACE) { spd = kartspeed_cons_t[serverlist[slindex].info.kartvars & SV_SPEEDMASK].strvalue; @@ -8405,9 +8496,6 @@ static void M_DrawConnectMenu(void) V_DrawSmallString(currentMenu->x+132, S_LINEY(i)+8, globalflags, va("(%s Speed)", spd)); } - if (serverlist[slindex].info.kartvars & SV_PASSWORD) - V_DrawFixedPatch((currentMenu->x - 9) << FRACBITS, (S_LINEY(i)) << FRACBITS, FRACUNIT, globalflags & (~V_ALLOWLOWERCASE), W_CachePatchName("SERVLOCK", PU_CACHE), NULL); - MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL; } @@ -8599,7 +8687,7 @@ static void M_ConnectMenuModChecks(INT32 choice) if (modifiedgame) { - M_StartMessage(M_GetText("Add-ons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing add-ons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER); + M_StartMessage(M_GetText("Addons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing addons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER); return; } @@ -8737,11 +8825,6 @@ static void M_StartServer(INT32 choice) // Still need to reset devmode cv_debug = 0; - if (strlen(cv_dummyjoinpassword.string) > 0) - D_SetJoinPassword(cv_dummyjoinpassword.string); - else - joinpasswordset = false; - if (demo.playback) G_StopDemo(); if (metalrecording) @@ -11157,25 +11240,6 @@ static void M_QuitSRB2(INT32 choice) // OpenGL specific options // ===================================================================== -#define FOG_COLOR_ITEM 1 -// =================== -// M_OGL_DrawFogMenu() -// =================== -static void M_OGL_DrawFogMenu(void) -{ - INT32 mx, my; - - mx = currentMenu->x; - my = currentMenu->y; - M_DrawGenericMenu(); // use generic drawer for cursor, items and title - V_DrawString(BASEVIDWIDTH - mx - V_StringWidth(cv_grfogcolor.string, 0), - my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, highlightflags, cv_grfogcolor.string); - // blink cursor on FOG_COLOR_ITEM if selected - if (itemOn == FOG_COLOR_ITEM && skullAnimCounter < 4) - V_DrawCharacter(BASEVIDWIDTH - mx, - my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, '_' | 0x80,false); -} - // ===================== // M_OGL_DrawColorMenu() // ===================== @@ -11189,61 +11253,4 @@ static void M_OGL_DrawColorMenu(void) V_DrawString(mx, my + currentMenu->menuitems[0].alphaKey - 10, highlightflags, "Gamma correction"); } - -//=================== -// M_HandleFogColor() -//=================== -static void M_HandleFogColor(INT32 choice) -{ - size_t i, l; - char temp[8]; - boolean exitmenu = false; // exit to previous menu and send name change - - switch (choice) - { - case KEY_DOWNARROW: - S_StartSound(NULL, sfx_menu1); - itemOn++; - break; - - case KEY_UPARROW: - S_StartSound(NULL, sfx_menu1); - itemOn--; - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_BACKSPACE: - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp)-1; - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[i + 6 - l] = temp[i]; - break; - - default: - if ((choice >= '0' && choice <= '9') || (choice >= 'a' && choice <= 'f') - || (choice >= 'A' && choice <= 'F')) - { - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp); - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[5 - i] = temp[l - i]; - cv_grfogcolor.zstring[5] = (char)choice; - } - break; - } - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} #endif diff --git a/src/m_menu.h b/src/m_menu.h index b00557cc..1ad20c77 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -31,6 +31,9 @@ // Does all the real work of the menu interaction. boolean M_Responder(event_t *ev); +// Called by main loop, runs for demo playback. If this returns true, nullify any further user input. +boolean M_DemoResponder(event_t *ev); + // Called by main loop, only used for menu (skull cursor) animation. void M_Ticker(void); @@ -56,6 +59,9 @@ void M_SortServerList(void); // Draws a box with a texture inside as background for messages void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines); +// Used in d_netcmd to restart time attack +void M_ModeAttackRetry(INT32 choice); + // the function to show a message box typing with the string inside // string must be static (not in the stack) // routine is a function taking a INT32 in parameter @@ -121,7 +127,6 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); #define IT_CV_NOPRINT 1536 #define IT_CV_NOMOD 2048 #define IT_CV_INVISSLIDER 2560 -#define IT_CV_PASSWORD 3072 //call/submenu specific // There used to be a lot more here but ... diff --git a/src/m_misc.c b/src/m_misc.c index f4a4ec29..87d648b2 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -30,6 +30,7 @@ #include "g_game.h" #include "m_misc.h" #include "hu_stuff.h" +#include "st_stuff.h" #include "v_video.h" #include "z_zone.h" #include "g_input.h" @@ -57,7 +58,7 @@ typedef off_t off64_t; #endif #endif -#if defined(__MINGW32__) && ((__GNUC__ > 7) || (__GNUC__ == 6 && __GNUC_MINOR__ >= 3)) +#if defined(__MINGW32__) && ((__GNUC__ > 7) || (__GNUC__ == 6 && __GNUC_MINOR__ >= 3)) && (__GNUC__ < 8) #define PRIdS "u" #elif defined (_WIN32) #define PRIdS "Iu" @@ -586,6 +587,21 @@ void M_SaveConfig(const char *filename) fclose(f); } +// ========================================================================== +// SCREENSHOTS +// ========================================================================== +static UINT8 screenshot_palette[768]; +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]; + screenshot_palette[i] = locpal.s.red; + screenshot_palette[i+1] = locpal.s.green; + screenshot_palette[i+2] = locpal.s.blue; + } +} #if NUMSCREENS > 2 static const char *Newsnapshotfile(const char *pathname, const char *ext) @@ -1017,6 +1033,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; const char *freename = NULL; boolean ret = false; @@ -1032,10 +1049,8 @@ static inline moviemode_t M_StartMovieAPNG(const char *pathname) return MM_OFF; } - if (rendermode == render_soft) - ret = M_SetupaPNG(va(pandf,pathname,freename), W_CacheLumpName(GetPalette(), PU_CACHE)); - else - ret = M_SetupaPNG(va(pandf,pathname,freename), NULL); + if (rendermode == render_soft) M_CreateScreenShotPalette(); + ret = M_SetupaPNG(va(pandf,pathname,freename), (palette = screenshot_palette)); if (!ret) { @@ -1100,12 +1115,8 @@ void M_StartMovie(void) switch (cv_moviemode.value) { case MM_GIF: - if (rendermode == render_soft) - { - moviemode = M_StartMovieGIF(pathname); - break; - } - /* FALLTHRU */ + moviemode = M_StartMovieGIF(pathname); + break; case MM_APNG: moviemode = M_StartMovieAPNG(pathname); break; @@ -1238,7 +1249,7 @@ void M_StopMovie(void) * \param data The image data. * \param width Width of the picture. * \param height Height of the picture. - * \param palette Palette of image data + * \param palette Palette of image data. * \note if palette is NULL, BGR888 format */ boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette) @@ -1260,8 +1271,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const return false; } - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, - PNG_error, PNG_warn); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); if (!png_ptr) { CONS_Debug(DBG_RENDER, "M_SavePNG: Error on initialize libpng\n"); @@ -1415,9 +1425,8 @@ void M_ScreenShot(void) } /** Takes a screenshot. - * The screenshot is saved as "kartxxxx.pcx" (or "kartxxxx.tga" in hardware - * rendermode) where xxxx is the lowest four-digit number for which a file - * does not already exist. + * The screenshot is saved as "srb2xxxx.png" where xxxx is the lowest + * four-digit number for which a file does not already exist. * * \sa HWR_ScreenShot */ @@ -1431,6 +1440,10 @@ void M_DoScreenShot(void) // Don't take multiple screenshots, obviously takescreenshot = false; + // how does one take a screenshot without a render system? + if (rendermode == render_none) + return; + if (cv_screenshot_option.value == 0) pathname = usehome ? srb2home : srb2path; else if (cv_screenshot_option.value == 1) @@ -1441,16 +1454,13 @@ void M_DoScreenShot(void) pathname = cv_screenshot_folder.string; #ifdef USE_PNG - if (rendermode != render_none) - freename = Newsnapshotfile(pathname,"png"); + freename = Newsnapshotfile(pathname,"png"); #else if (rendermode == render_soft) freename = Newsnapshotfile(pathname,"pcx"); - else if (rendermode != render_none) + else if (rendermode == render_opengl) freename = Newsnapshotfile(pathname,"tga"); #endif - else - I_Error("Can't take a screenshot without a render system"); if (rendermode == render_soft) { @@ -1464,18 +1474,16 @@ void M_DoScreenShot(void) // save the pcx file #ifdef HWRENDER - if (rendermode != render_soft) + if (rendermode == render_opengl) ret = HWR_Screenshot(va(pandf,pathname,freename)); else #endif - if (rendermode != render_none) { + M_CreateScreenShotPalette(); #ifdef USE_PNG - ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, - W_CacheLumpName(GetPalette(), PU_CACHE)); + ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette); #else - ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height, - W_CacheLumpName(GetPalette(), PU_CACHE)); + ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette); #endif } @@ -1483,14 +1491,14 @@ failure: if (ret) { if (moviemode != MM_SCREENSHOT) - CONS_Printf(M_GetText("screen shot %s saved in %s\n"), freename, pathname); + CONS_Printf(M_GetText("Screen shot %s saved in %s\n"), freename, pathname); } else { if (freename) - CONS_Printf(M_GetText("Couldn't create screen shot %s in %s\n"), freename, pathname); + CONS_Alert(CONS_ERROR, M_GetText("Couldn't create screen shot %s in %s\n"), freename, pathname); else - CONS_Printf(M_GetText("Couldn't create screen shot (all 10000 slots used!) in %s\n"), pathname); + CONS_Alert(CONS_ERROR, M_GetText("Couldn't create screen shot in %s (all 10000 slots used!)\n"), pathname); if (moviemode == MM_SCREENSHOT) M_StopMovie(); diff --git a/src/nds/r_nds3d.c b/src/nds/r_nds3d.c index dbdcec15..6734e8c1 100644 --- a/src/nds/r_nds3d.c +++ b/src/nds/r_nds3d.c @@ -160,7 +160,7 @@ void NDS3D_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts z = pOutVerts[index].z; } - glTexCoord2f(pOutVerts[index].sow, pOutVerts[index].tow); + glTexCoord2f(pOutVerts[index].s, pOutVerts[index].tow); glVertex3f(x,y,z); } glEnd(); diff --git a/src/p_enemy.c b/src/p_enemy.c index 1795a304..a3bf5491 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3929,6 +3929,9 @@ static inline boolean PIT_GrenadeRing(mobj_t *thing) if (!grenade) return false; + if (grenade->flags2 & MF2_DEBRIS) + return false; + if (thing->type != MT_PLAYER) // Don't explode for anything but an actual player. return true; @@ -3977,6 +3980,9 @@ void A_GrenadeRing(mobj_t *actor) return; #endif + if (actor->flags2 & MF2_DEBRIS) + return; + if (actor->state == &states[S_SSMINE_DEPLOY8]) explodedist = (3*explodedist)/2; @@ -4001,6 +4007,9 @@ static inline boolean PIT_MineExplode(mobj_t *thing) if (!grenade || P_MobjWasRemoved(grenade)) return false; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot + if (grenade->flags2 & MF2_DEBRIS) // don't explode twice + return false; + if (thing == grenade || thing->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop! return true; @@ -4023,8 +4032,6 @@ static inline boolean PIT_MineExplode(mobj_t *thing) thing->z - grenade->z) > explodedist) return true; // Too far away - grenade->flags2 |= MF2_DEBRIS; - 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 @@ -4045,6 +4052,9 @@ void A_MineExplode(mobj_t *actor) return; #endif + if (actor->flags2 & MF2_DEBRIS) + return; + type = (mobjtype_t)locvar1; // Use blockmap to check for nearby shootables @@ -4053,6 +4063,8 @@ void A_MineExplode(mobj_t *actor) xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT; xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT; + BMBOUNDFIX (xl, xh, yl, yh); + grenade = actor; for (by = yl; by <= yh; by++) @@ -4068,6 +4080,8 @@ void A_MineExplode(mobj_t *actor) K_SpawnMineExplosion(actor, SKINCOLOR_KETCHUP); P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND); + + actor->flags2 |= MF2_DEBRIS; // Set this flag to ensure that the explosion won't be effective more than 1 frame. } //} diff --git a/src/p_inter.c b/src/p_inter.c index a910445d..abb12811 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2036,7 +2036,7 @@ boolean P_CheckRacers(void) if (i == MAXPLAYERS) // finished { - countdown = countdown2 = 0; + racecountdown = exitcountdown = 0; return true; } @@ -2063,13 +2063,13 @@ boolean P_CheckRacers(void) if (j == MAXPLAYERS) // finish anyways, force a time over { P_DoTimeOver(&players[i]); - countdown = countdown2 = 0; + racecountdown = exitcountdown = 0; return true; } } } - if (!countdown) // Check to see if the winners have finished, to set countdown. + if (!racecountdown) // Check to see if the winners have finished, to set countdown. { UINT8 numingame = 0, numexiting = 0; UINT8 winningpos = 1; @@ -2088,7 +2088,7 @@ boolean P_CheckRacers(void) winningpos++; if (numexiting >= winningpos) - countdown = (((netgame || multiplayer) ? cv_countdowntime.value : 30)*TICRATE) + 1; // 30 seconds to finish, get going! + racecountdown = (((netgame || multiplayer) ? cv_countdowntime.value : 30)*TICRATE) + 1; // 30 seconds to finish, get going! } return false; diff --git a/src/p_local.h b/src/p_local.h index 0d0ddc89..7216326d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -109,6 +109,20 @@ typedef struct camera_s fixed_t pan; } camera_t; +// demo freecam or something before i commit die +struct demofreecam_s { + + camera_t *cam; // this is useful when the game is paused, notably + mobj_t *soundmobj; // mobj to play sound from, used in s_sound + + angle_t localangle; // keeps track of the cam angle for cmds + angle_t localaiming; // ditto with aiming + boolean turnheld; // holding turn button for gradual turn speed + boolean keyboardlook; // keyboard look +}; + +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; @@ -133,7 +147,9 @@ 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); 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); diff --git a/src/p_map.c b/src/p_map.c index d9b72365..4664703d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -732,7 +732,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0))) + if (((tmthing->target == thing) || (tmthing->target == thing->target)) && ((tmthing->threshold > 0 && thing->type == MT_PLAYER) || (thing->type != MT_PLAYER && thing->threshold > 0))) return true; if (tmthing->health <= 0 || thing->health <= 0) diff --git a/src/p_saveg.c b/src/p_saveg.c index 7d2e9a30..5bbba1f2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3264,8 +3264,8 @@ static void P_NetArchiveMisc(void) WRITEINT16(save_p, scrambletotal); WRITEINT16(save_p, scramblecount); - WRITEUINT32(save_p, countdown); - WRITEUINT32(save_p, countdown2); + WRITEUINT32(save_p, racecountdown); + WRITEUINT32(save_p, exitcountdown); WRITEFIXED(save_p, gravity); WRITEFIXED(save_p, mapobjectscale); @@ -3373,8 +3373,8 @@ static inline boolean P_NetUnArchiveMisc(void) scrambletotal = READINT16(save_p); scramblecount = READINT16(save_p); - countdown = READUINT32(save_p); - countdown2 = READUINT32(save_p); + racecountdown = READUINT32(save_p); + exitcountdown = READUINT32(save_p); gravity = READFIXED(save_p); mapobjectscale = READFIXED(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index bf13971b..decdc529 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -465,11 +465,7 @@ static void P_LoadRawSegs(UINT8 *data, size_t i) li->length = P_SegLength(li); #ifdef HWRENDER if (rendermode == render_opengl) - { li->flength = P_SegLengthFloat(li); - //Hurdler: 04/12/2000: for now, only used in hardware mode - li->lightmaps = NULL; // list of static lightmap for this seg - } li->pv1 = li->pv2 = NULL; #endif @@ -1407,11 +1403,12 @@ 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; + UINT32 cr, cg, cb; for (i = 0; i < numsides; i++) { @@ -1490,16 +1487,43 @@ static void P_LoadRawSideDefs2(void *data) { col = msd->toptexture; - sec->extra_colormap->rgba = - (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) + - (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) + - (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16); + // 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. + + cr = (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0); + cg = (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8); + cb = (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16); + +#ifdef GLENCORE + if (encoremap) + { + j = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; + //CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", j, encoremap[j]); -- moved encoremap upwards for optimisation + cr = pLocalPalette[j].s.red; + cg = pLocalPalette[j].s.green; + cb = pLocalPalette[j].s.blue; + } +#endif + + sec->extra_colormap->rgba = cr + cg + cb; // 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; @@ -1508,10 +1532,24 @@ static void P_LoadRawSideDefs2(void *data) { col = msd->bottomtexture; - sec->extra_colormap->fadergba = - (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0) + - (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8) + - (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16); + // do the exact same thing as above here. + + cr = (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0); + cg = (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8); + cb = (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16); + +#ifdef GLENCORE + if (encoremap) + { + j = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; + //CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", j, encoremap[j]); -- moved encoremap upwards for optimisation + cr = pLocalPalette[j].s.red; + cg = pLocalPalette[j].s.green; + cb = pLocalPalette[j].s.blue; + } +#endif + + sec->extra_colormap->fadergba = cr + cg + cb; // alpha if (msd->bottomtexture[7]) @@ -1658,6 +1696,7 @@ static void P_LoadRawSideDefs2(void *data) R_ClearTextureNumCache(true); } + // Delay loading texture names until after loaded linedefs. static void P_LoadSideDefs2(lumpnum_t lumpnum) { @@ -2344,7 +2383,7 @@ static void P_LevelInitStuff(void) players[i].lives = 1; // SRB2Kart #endif - players[i].realtime = countdown = countdown2 = 0; + players[i].realtime = racecountdown = exitcountdown = 0; curlap = bestlap = 0; // SRB2Kart players[i].gotcontinue = false; @@ -2850,26 +2889,34 @@ boolean P_SetupLevel(boolean skipprecip) // Encore mode fade to pink to white // This is handled BEFORE sounds are stopped. - if (rendermode != render_none && encoremode && !prevencoremode && !demo.rewinding) + if (encoremode && !prevencoremode && !demo.rewinding) { tic_t locstarttime, endtime, nowtime; - S_StopMusic(); // er, about that... + if (rendermode != render_none) + { + S_StopMusic(); // er, about that... - S_StartSound(NULL, sfx_ruby1); + S_StartSound(NULL, sfx_ruby1); - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 122); + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 122); - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_speclevel_towhite], false); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_speclevel_towhite], false); - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); - - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_level_final], false); + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_level_final], false); + } + else //dedicated servers can call this now, to wait the appropriate amount of time for clients to wipe + { + F_RunWipe(wipedefs[wipe_speclevel_towhite], false); + F_RunWipe(wipedefs[wipe_level_final], false); + } + locstarttime = nowtime = lastwipetic; endtime = locstarttime + (3*TICRATE)/2; @@ -2902,13 +2949,20 @@ boolean P_SetupLevel(boolean skipprecip) // Let's fade to white here // But only if we didn't do the encore startup wipe - if (rendermode != render_none && !ranspecialwipe && !demo.rewinding) + if (!ranspecialwipe && !demo.rewinding) { - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); + if(rendermode != render_none) + { + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); - F_WipeEndScreen(); - F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); + F_WipeEndScreen(); + F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); + } + else //dedicated servers + { + F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false); + } } // Reset the palette now all fades have been done @@ -3089,10 +3143,6 @@ boolean P_SetupLevel(boolean skipprecip) #ifdef HWRENDER // not win32 only 19990829 by Kin if (rendermode != render_soft && rendermode != render_none) { -#ifdef ALAM_LIGHTING - // BP: reset light between levels (we draw preview frame lights on current frame) - HWR_ResetLights(); -#endif // Correct missing sidedefs & deep water trick HWR_CorrectSWTricks(); HWR_CreatePlanePolygons((INT32)numnodes - 1); @@ -3201,8 +3251,9 @@ boolean P_SetupLevel(boolean skipprecip) if (!dedicated) { - for (i = 0; i <= splitscreen; i++) - P_SetupCamera(displayplayers[i], &camera[i]); + if (!demo.freecam) + for (i = 0; i <= splitscreen; i++) + P_SetupCamera(displayplayers[i], &camera[i]); // Salt: CV_ClearChangedFlags() messes with your settings :( /*if (!cv_cam_height.changed) @@ -3328,7 +3379,7 @@ boolean P_SetupLevel(boolean skipprecip) if (loadprecip) // uglier hack { // to make a newly loaded level start on the second frame. - INT32 buf = gametic % BACKUPTICS; + INT32 buf = gametic % TICQUEUE; for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) diff --git a/src/p_spec.c b/src/p_spec.c index a08bdbc3..165a2eba 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1944,6 +1944,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || 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 triggerline->special = 0; // Clear it out @@ -1981,6 +1982,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) if (lines[masterline].special == 313 || lines[masterline].special == 399 || lines[masterline].special == 328 + || lines[masterline].special == 323 // Each-time executors handle themselves, too || lines[masterline].special == 301 // Each time || lines[masterline].special == 306 // Character ability - Each time @@ -3812,12 +3814,14 @@ DoneSection2: { const fixed_t hscale = mapobjectscale + (mapobjectscale - player->mo->scale); const fixed_t minspeed = 24*hscale; + angle_t pushangle = FixedHypot(player->mo->momx, player->mo->momy) ? R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy) : player->mo->angle; + // if we have no speed for SOME REASON, use the player's angle, otherwise we'd be forcefully thrusted to what I can only assume is angle 0 if (player->mo->eflags & MFE_SPRUNG) break; if (player->speed < minspeed) // Push forward to prevent getting stuck - P_InstaThrust(player->mo, player->mo->angle, minspeed); + P_InstaThrust(player->mo, pushangle, minspeed); player->kartstuff[k_pogospring] = 1; K_DoPogoSpring(player->mo, 0, 1); @@ -3833,14 +3837,16 @@ DoneSection2: const fixed_t hscale = mapobjectscale + (mapobjectscale - player->mo->scale); const fixed_t minspeed = 24*hscale; const fixed_t maxspeed = 28*hscale; + angle_t pushangle = FixedHypot(player->mo->momx, player->mo->momy) ? R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy) : player->mo->angle; + // if we have no speed for SOME REASON, use the player's angle, otherwise we'd be forcefully thrusted to what I can only assume is angle 0 if (player->mo->eflags & MFE_SPRUNG) break; if (player->speed > maxspeed) // Prevent overshooting jumps - P_InstaThrust(player->mo, R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy), maxspeed); + P_InstaThrust(player->mo, pushangle, maxspeed); else if (player->speed < minspeed) // Push forward to prevent getting stuck - P_InstaThrust(player->mo, player->mo->angle, minspeed); + P_InstaThrust(player->mo, pushangle, minspeed); player->kartstuff[k_pogospring] = 2; K_DoPogoSpring(player->mo, 0, 1); @@ -5654,7 +5660,7 @@ static void P_RunLevelLoadExecutors(void) for (i = 0; i < numlines; i++) { - if (lines[i].special == 399 || lines[i].special == 328) + if (lines[i].special == 399 || lines[i].special == 328 || lines[i].special == 323) P_RunTriggerLinedef(&lines[i], NULL, NULL); } } @@ -6554,6 +6560,11 @@ void P_SpawnSpecials(INT32 fromnetsave) P_AddEachTimeThinker(§ors[sec], &lines[i]); } break; + // Record attack only linedef exec + case 323: + if (!modeattacking) + lines[i].special = 0; + break; case 328: // Encore-only linedef execute on map load if (!encoremode) diff --git a/src/p_tick.c b/src/p_tick.c index 2502c721..eaa8b462 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -597,6 +597,8 @@ void P_Ticker(boolean run) leveltime = (leveltime-1) & ~3; G_PreviewRewind(leveltime); } + else if (demo.freecam && democam.cam) // special case: allow freecam to MOVE during pause! + P_DemoCameraMovement(democam.cam); return; } @@ -689,7 +691,10 @@ void P_Ticker(boolean run) if (run) leveltime++; - timeinmap++; + + // as this is mostly used for HUD stuff, add the record attack specific hack to it as well! + if (!(modeattacking && !demo.playback) || leveltime >= starttime - TICRATE*4) + timeinmap++; /*if (G_TagGametype()) P_DoTagStuff(); @@ -715,15 +720,15 @@ void P_Ticker(boolean run) } } - if (countdown > 1) - countdown--; + if (racecountdown > 1) + racecountdown--; - if (countdown2) - countdown2--; + if (exitcountdown > 1) + exitcountdown--; - if (indirectitemcooldown) + if (indirectitemcooldown > 1) indirectitemcooldown--; - if (hyubgone) + if (hyubgone > 1) hyubgone--; if (G_BattleGametype()) diff --git a/src/p_user.c b/src/p_user.c index ced8b2da..03f8f0fb 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -29,6 +29,7 @@ #include "m_random.h" #include "m_misc.h" #include "i_video.h" +#include "i_joy.h" #include "p_slopes.h" #include "p_spec.h" #include "r_splats.h" @@ -1726,8 +1727,8 @@ void P_DoPlayerExit(player_t *player) P_EndingMusic(player); // SRB2kart 120217 - //if (!countdown2) - //countdown2 = countdown + 8*TICRATE; + //if (!exitcountdown) + //exitcountdown = racecountdown + 8*TICRATE; if (P_CheckRacers()) player->exiting = raceexittime+1; @@ -7087,7 +7088,7 @@ static void P_DeathThink(player_t *player) } // Keep time rolling - if (!(countdown2 && !countdown) && !(player->exiting || mapreset) && !(player->pflags & PF_TIMEOVER)) + if (!(exitcountdown && !racecountdown) && !(player->exiting || mapreset) && !(player->pflags & PF_TIMEOVER)) { if (leveltime >= starttime) { @@ -7204,11 +7205,249 @@ fixed_t t_cam4_rotate = -42; #define MAXCAMERADIST 140*FRACUNIT // Max distance the camera can be in front of the player (2D mode) +// 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[2] = {25<>16, 50<>16}; +static fixed_t sidemove[2] = {2<>16, 4<>16}; +static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn + +static ticcmd_t cameracmd; + +struct demofreecam_s democam; + +// called by m_menu to reinit cam input every time it's toggled +void P_InitCameraCmd(void) +{ + memset(&cameracmd, 0, sizeof(ticcmd_t)); // initialize cmd +} + +static ticcmd_t *P_CameraCmd(camera_t *cam) +{ + INT32 laim, th, tspeed, forward, side, axis; //i + const INT32 speed = 1; + // 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; + + 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; + + usejoystick = true; + turnright = InputDown(gc_turnright, 1); + turnleft = InputDown(gc_turnleft, 1); + + axis = JoyAxis(AXISTURN, 1); + + if (encoremode) + { + turnright ^= turnleft; // swap these using three XORs + turnleft ^= turnright; + turnright ^= turnleft; + axis = -axis; + } + + if (axis != 0) + { + turnright = turnright || (axis > 0); + turnleft = turnleft || (axis < 0); + } + forward = side = 0; + + // use two stage accelerative turning + // on the keyboard and joystick + if (turnleft || turnright) + th += 1; + else + th = 0; + + if (th < SLOWTURNTICS) + tspeed = 2; // slow turn + else + tspeed = speed; + + // let movement keys cancel each other out + if (turnright && !(turnleft)) + { + cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed])); + side += sidemove[1]; + } + else if (turnleft && !(turnright)) + { + cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed])); + side -= sidemove[1]; + } + + cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8))); + + axis = JoyAxis(AXISMOVE, 1); + if (InputDown(gc_accelerate, 1) || (usejoystick && axis > 0)) + cmd->buttons |= BT_ACCELERATE; + axis = JoyAxis(AXISBRAKE, 1); + if (InputDown(gc_brake, 1) || (usejoystick && axis > 0)) + cmd->buttons |= BT_BRAKE; + axis = JoyAxis(AXISAIM, 1); + if (InputDown(gc_aimforward, 1) || (usejoystick && axis < 0)) + forward += forwardmove[1]; + if (InputDown(gc_aimbackward, 1) || (usejoystick && axis > 0)) + forward -= forwardmove[1]; + + // fire with any button/key + axis = JoyAxis(AXISFIRE, 1); + if (InputDown(gc_fire, 1) || (usejoystick && axis > 0)) + cmd->buttons |= BT_ATTACK; + + // spectator aiming shit, ahhhh... + player_invert = invertmouse ? -1 : 1; + screen_invert = 1; // nope + + // mouse look stuff (mouse look is not the same as mouse aim) + kbl = false; + + // looking up/down + laim += (mlooky<<19)*player_invert*screen_invert; + + axis = JoyAxis(AXISLOOK, 1); + + // spring back if not using keyboard neither mouselookin' + if (!kbl && !lookaxis && !mouseaiming) + laim = 0; + + if (InputDown(gc_lookup, 1) || (axis < 0)) + { + laim += KB_LOOKSPEED * screen_invert; + kbl = true; + } + else if (InputDown(gc_lookdown, 1) || (axis > 0)) + { + laim -= 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); + + mousex = mousey = mlooky = 0; + + if (forward > MAXPLMOVE) + forward = MAXPLMOVE; + else if (forward < -MAXPLMOVE) + forward = -MAXPLMOVE; + + if (side > MAXPLMOVE) + side = MAXPLMOVE; + else if (side < -MAXPLMOVE) + side = -MAXPLMOVE; + + if (forward || side) + { + cmd->forwardmove = (SINT8)(cmd->forwardmove + forward); + cmd->sidemove = (SINT8)(cmd->sidemove + side); + } + + lang += (cmd->angleturn<<16); + + democam.localangle = lang; + democam.localaiming = laim; + democam.turnheld = th; + democam.keyboardlook = kbl; + + return cmd; +} + +void P_DemoCameraMovement(camera_t *cam) +{ + ticcmd_t *cmd; + angle_t thrustangle; + mobj_t *awayviewmobj_hack; + player_t *lastp; + + // update democam stuff with what we got here: + democam.cam = cam; + democam.localangle = cam->angle; + democam.localaiming = cam->aiming; + + // first off we need to get button input + cmd = P_CameraCmd(cam); + + cam->aiming = cmd->aiming<angle = cmd->angleturn<<16; + + // camera movement: + + if (cmd->buttons & BT_ACCELERATE) + cam->z += 32*mapobjectscale; + else if (cmd->buttons & BT_BRAKE) + cam->z -= 32*mapobjectscale; + + // if you hold item, you will lock on to displayplayer. (The last player you were ""f12-ing"") + if (cmd->buttons & BT_ATTACK) + { + lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot. + cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y); + cam->aiming = R_PointToAngle2(0, cam->z, R_PointToDist2(cam->x, cam->y, lastp->mo->x, lastp->mo->y), lastp->mo->z + lastp->mo->scale*128*P_MobjFlip(lastp->mo)); // This is still unholy. Aim a bit above their heads. + } + + + cam->momx = cam->momy = cam->momz = 0; + if (cmd->forwardmove != 0) + { + + thrustangle = cam->angle >> ANGLETOFINESHIFT; + + cam->x += FixedMul(cmd->forwardmove*mapobjectscale, FINECOSINE(thrustangle)); + cam->y += FixedMul(cmd->forwardmove*mapobjectscale, FINESINE(thrustangle)); + cam->z += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(cam->aiming)); + // momentums are useless here, directly add to the coordinates + + // this.......... doesn't actually check for floors and walls and whatnot but the function to do that is a pure mess so fuck that. + // besides freecam going inside walls sounds pretty cool on paper. + } + + // awayviewmobj hack; this is to prevent us from hearing sounds from the player's perspective + + awayviewmobj_hack = P_SpawnMobj(cam->x, cam->y, cam->z, MT_THOK); + awayviewmobj_hack->tics = 2; + awayviewmobj_hack->flags2 |= MF2_DONTDRAW; + + democam.soundmobj = awayviewmobj_hack; + + // update subsector to avoid crashes; + cam->subsector = R_PointInSubsector(cam->x, cam->y); +} + void P_ResetCamera(player_t *player, camera_t *thiscam) { tic_t tries = 0; fixed_t x, y, z; + if (demo.freecam) + return; // do not reset the camera there. + if (!player->mo) return; @@ -7263,6 +7502,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; #endif + democam.soundmobj = NULL; // reset this each frame, we don't want the game crashing for stupid reasons now do we + // We probably shouldn't move the camera if there is no player or player mobj somehow if (!player || !player->mo) return true; @@ -7271,6 +7512,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) return true; + if (demo.freecam) + { + P_DemoCameraMovement(thiscam); + return true; + } + mo = player->mo; #ifndef NOCLIPCAM @@ -7426,7 +7673,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall const INT32 timeovercam = max(0, min(180, (player->kartstuff[k_timeovercam] - 2*TICRATE)*15)); camrotate += timeovercam; } - else if (leveltime < introtime) // Whoooshy camera! + else if (leveltime < introtime && !(modeattacking && !demo.playback)) // Whoooshy camera! (don't do this in RA when we PLAY, still do it in replays however~) { const INT32 introcam = (introtime - leveltime); camrotate += introcam*5; @@ -8057,8 +8304,8 @@ void P_DoTimeOver(player_t *player) P_EndingMusic(player); - if (!countdown2) - countdown2 = 5*TICRATE; + if (!exitcountdown) + exitcountdown = 5*TICRATE; } // @@ -8201,7 +8448,7 @@ void P_PlayerThink(player_t *player) // begin the drown music for countdown! // SRB2Kart: despite how perfect this is, it's disabled FOR A REASON - /*if (countdown == 11*TICRATE - 1) + /*if (racecountdown == 11*TICRATE - 1) { if (P_IsLocalPlayer(player)) S_ChangeMusicInternal("drown", false); @@ -8209,7 +8456,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! - else if (countdown == 1 && !player->exiting && !player->spectator && player->lives > 0) + else if (racecountdown == 1 && !player->exiting && !player->spectator && player->lives > 0) { P_DoTimeOver(player); @@ -8223,10 +8470,10 @@ void P_PlayerThink(player_t *player) if (player->exiting > 1 && (player->exiting < raceexittime+2 || !G_RaceGametype())) // SRB2kart - "&& player->exiting > 1" player->exiting--; - if (player->exiting && countdown2) + if (player->exiting && exitcountdown) player->exiting = 99; // SRB2kart - if (player->exiting == 2 || countdown2 == 2) + if (player->exiting == 2 || exitcountdown == 2) { if (cv_playersforexit.value) // Count to be sure everyone's exited { diff --git a/src/r_bsp.c b/src/r_bsp.c index 296cbbe8..43cb6432 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -37,7 +37,7 @@ drawseg_t *ds_p = NULL; // indicates doors closed wrt automap bugfix: INT32 doorclosed; -static boolean R_NoEncore(sector_t *sector, boolean ceiling) +boolean R_NoEncore(sector_t *sector, boolean ceiling) { boolean invertencore = (GETSECSPECIAL(sector->special, 2) == 15); #if 0 // perfect implementation diff --git a/src/r_bsp.h b/src/r_bsp.h index e3662e2e..1e4ca68f 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -40,6 +40,10 @@ 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); diff --git a/src/r_data.c b/src/r_data.c index 7fb11855..25387dec 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -198,7 +198,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) int x, x1, x2, i; size_t blocksize; column_t *patchcol; - UINT32 *colofs; + UINT8 *colofs; I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; @@ -219,10 +219,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) holey = true; - colofs = (UINT32 *)realpatch->columnofs; + colofs = (UINT8 *)realpatch->columnofs; for (x = 0; x < texture->width && !holey; x++) { - column_t *col = (column_t *)((UINT8 *)realpatch + LONG(colofs[x])); + column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); INT32 topdelta, prevdelta = -1, y = 0; while (col->topdelta != 0xff) { @@ -250,11 +250,11 @@ static UINT8 *R_GenerateTexture(size_t texnum) texturememory += blocksize; // use the patch's column lookup - colofs = (UINT32 *)(void *)(block + 8); - texturecolumnofs[texnum] = colofs; + colofs = (block + 8); + texturecolumnofs[texnum] = (UINT32 *)colofs; blocktex = block; for (x = 0; x < texture->width; x++) - colofs[x] = LONG(LONG(colofs[x]) + 3); + *(UINT32 *)&colofs[x<<2] = LONG(LONG(*(UINT32 *)&colofs[x<<2]) + 3); goto done; } @@ -270,8 +270,8 @@ static UINT8 *R_GenerateTexture(size_t texnum) memset(block, 0xF7, blocksize+1); // Transparency hack // columns lookup table - colofs = (UINT32 *)(void *)block; - texturecolumnofs[texnum] = colofs; + colofs = block; + texturecolumnofs[texnum] = (UINT32 *)colofs; // texture data after the lookup table blocktex = block + (texture->width*4); @@ -296,8 +296,8 @@ static UINT8 *R_GenerateTexture(size_t texnum) patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); // generate column ofset lookup - colofs[x] = LONG((x * texture->height) + (texture->width*4)); - R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height); + *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); + R_DrawColumnInCache(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch->originy, texture->height); } } @@ -1177,7 +1177,6 @@ void R_ClearColormaps(void) // static double deltas[256][3], map[256][3]; -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); #ifdef HASINVERT @@ -1403,7 +1402,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) // Thanks to quake2 source! // utils3/qdata/images.c -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; diff --git a/src/r_data.h b/src/r_data.h index 640b3030..bd404789 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -98,6 +98,10 @@ void R_MakeInvertmap(void); #endif const char *R_ColormapNameForNum(INT32 num); +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); + extern INT32 numtextures; +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); + #endif diff --git a/src/r_defs.h b/src/r_defs.h index 52a3be80..00036e9e 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -526,31 +526,6 @@ 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. // @@ -579,8 +554,6 @@ 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? diff --git a/src/r_main.c b/src/r_main.c index 358a24bb..2ec06497 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -137,7 +137,7 @@ static CV_PossibleValue_t drawdist_precip_cons_t[] = { {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, {0, "None"}, {0, NULL}}; -static CV_PossibleValue_t fov_cons_t[] = {{0, "MIN"}, {179*FRACUNIT, "MAX"}, {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 translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; @@ -181,7 +181,9 @@ consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_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}; -consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange, 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}; // 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}; @@ -540,9 +542,9 @@ static void R_InitTextureMapping(void) for (i = 0; i < FINEANGLES/2; i++) { - if (FINETANGENT(i) > FRACUNIT*2) + if (FINETANGENT(i) > fovtan*2) t = -1; - else if (FINETANGENT(i) < -FRACUNIT*2) + else if (FINETANGENT(i) < -fovtan*2) t = viewwidth+1; else { @@ -686,11 +688,6 @@ void R_ExecuteSetViewSize(void) R_InitTextureMapping(); -#ifdef HWRENDER - if (rendermode != render_soft) - HWR_InitTextureMapping(); -#endif - // thing clipping for (i = 0; i < viewwidth; i++) screenheightarray[i] = (INT16)viewheight; @@ -820,29 +817,31 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) static mobj_t *viewmobj; -// WARNING: a should be unsigned but to add with 2048, it isn't! -#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS, fovtan) - // 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) { INT32 dy = 0; + + // 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 +#endif + ) + G_SoftwareClipAimingPitch((INT32 *)&aimingangle); + if (rendermode == render_soft) { - // clip it in the case we are looking a hardware 90 degrees full aiming - // (lmps, network and use F12...) - G_SoftwareClipAimingPitch((INT32 *)&aimingangle); - dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH; + dy = (AIMINGTODY(aimingangle)/fovtan) * viewwidth/BASEVIDWIDTH; yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)]; } centery = (viewheight/2) + dy; centeryfrac = centery<subsector) + if (thiscam->subsector && thiscam->subsector->sector) viewsector = thiscam->subsector->sector; else viewsector = R_PointInSubsector(viewx, viewy)->sector; @@ -1188,7 +1187,7 @@ void R_SetupFrame(player_t *player, boolean skybox) viewx += quake.x; viewy += quake.y; - if (viewmobj->subsector) + if (viewmobj->subsector && thiscam->subsector->sector) viewsector = viewmobj->subsector->sector; else viewsector = R_PointInSubsector(viewx, viewy)->sector; @@ -1551,9 +1550,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grgammagreen); CV_RegisterVar(&cv_grgammared); CV_RegisterVar(&cv_grfovchange); - CV_RegisterVar(&cv_grfog); - CV_RegisterVar(&cv_grfogcolor); - CV_RegisterVar(&cv_grsoftwarefog); #ifdef ALAM_LIGHTING CV_RegisterVar(&cv_grstaticlighting); CV_RegisterVar(&cv_grdynamiclighting); @@ -1563,6 +1559,9 @@ void R_RegisterEngineStuff(void) 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 diff --git a/src/r_things.c b/src/r_things.c index b2170924..59e14883 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -259,6 +259,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer if (rendermode != render_none) // not for psprite spritecachedinfo[numspritelumps].topoffset += 4<0 && SHORT(patch.topoffset)thinglist; thing; thing = thing->snext) { + split_drawsprite = false; + if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) continue; - if (splitscreen) + splitflags = thing->eflags & (MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); + + if (splitscreen && splitflags) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (viewssnum != 0) - continue; + if (viewssnum == 0) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP2) - if (viewssnum != 1) - continue; + if (viewssnum == 1) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (viewssnum != 2) - continue; + if (viewssnum == 2) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (viewssnum != 3) - continue; + if (viewssnum == 3) + split_drawsprite = true; } + else + split_drawsprite = true; + + if (!split_drawsprite) + continue; approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); @@ -1779,27 +1792,37 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) // Draw everything in sector, no checks for (thing = sec->thinglist; thing; thing = thing->snext) { + + split_drawsprite = false; + if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) continue; - if (splitscreen) + splitflags = thing->eflags & (MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4); + + if (splitscreen && splitflags) { if (thing->eflags & MFE_DRAWONLYFORP1) - if (viewssnum != 0) - continue; + if (viewssnum == 0) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP2) - if (viewssnum != 1) - continue; + if (viewssnum == 1) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1) - if (viewssnum != 2) - continue; + if (viewssnum == 2) + split_drawsprite = true; if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2) - if (viewssnum != 3) - continue; + if (viewssnum == 3) + split_drawsprite = true; } + else + split_drawsprite = true; + + if (!split_drawsprite) + continue; R_ProjectSprite(thing); } diff --git a/src/s_sound.c b/src/s_sound.c index 21b668f2..2c96d389 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -38,7 +38,7 @@ extern INT32 msg_id; #include "p_local.h" // camera info #include "m_misc.h" // for tunes command -#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) +#ifdef HAVE_BLUA #include "lua_hook.h" // MusicChange hook #endif @@ -442,7 +442,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) listener_t listener3 = {0,0,0,0}; listener_t listener4 = {0,0,0,0}; - mobj_t *listenmobj = players[displayplayers[0]].mo; + mobj_t *listenmobj = democam.soundmobj ? : players[displayplayers[0]].mo; mobj_t *listenmobj2 = NULL; mobj_t *listenmobj3 = NULL; mobj_t *listenmobj4 = NULL; @@ -903,7 +903,7 @@ void S_UpdateSounds(void) listener_t listener3; listener_t listener4; - mobj_t *listenmobj = players[displayplayers[0]].mo; + mobj_t *listenmobj = democam.soundmobj ? : players[displayplayers[0]].mo; mobj_t *listenmobj2 = NULL; mobj_t *listenmobj3 = NULL; mobj_t *listenmobj4 = NULL; @@ -1989,7 +1989,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 return; strncpy(newmusic, mmusic, 7); -#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) +#ifdef HAVE_BLUA if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) return; #endif diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 45b1faab..69b3465a 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -93,6 +93,7 @@ + @@ -222,7 +223,6 @@ - @@ -488,4 +488,4 @@ - \ No newline at end of file + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 8556627b..9e5b9837 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -231,9 +231,6 @@ Hw_Hardware - - Hw_Hardware - Hw_Hardware @@ -639,7 +636,7 @@ Hw_Hardware - + Hw_Hardware @@ -924,4 +921,4 @@ SDLApp - \ No newline at end of file + diff --git a/src/sdl/Srb2SDL-vc9.vcproj b/src/sdl/Srb2SDL-vc9.vcproj index 3898aeba..b21eedb8 100644 --- a/src/sdl/Srb2SDL-vc9.vcproj +++ b/src/sdl/Srb2SDL-vc9.vcproj @@ -2410,10 +2410,6 @@ RelativePath="..\hardware\hw_drv.h" > - - diff --git a/src/sdl/Srb2SDL.dsp b/src/sdl/Srb2SDL.dsp index 879113ca..ce35e2e2 100644 --- a/src/sdl/Srb2SDL.dsp +++ b/src/sdl/Srb2SDL.dsp @@ -7,19 +7,19 @@ CFG=Srb2SDL - 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 !MESSAGE NMAKE /f "Srb2SDL.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Srb2SDL.mak" CFG="Srb2SDL - Win32 Debug" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "Srb2SDL - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Srb2SDL - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -85,7 +85,7 @@ LINK32=link.exe # ADD LINK32 SDL.lib SDL_mixer.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /pdb:"C:\srb2demo2\srb2sdldebug.pdb" /debug /machine:I386 /out:"C:\srb2demo2\srb2sdldebug.exe" /pdbtype:sept # SUBTRACT LINK32 /pdb:none -!ENDIF +!ENDIF # Begin Target @@ -213,7 +213,7 @@ SOURCE=.\SDL_main\SDL_win32_main.c # PROP Exclude_From_Build 1 -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -274,7 +274,7 @@ InputName=tmap # End Custom Build -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -308,7 +308,7 @@ InputName=tmap_mmx # End Custom Build -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -339,7 +339,7 @@ InputName=tmap_vc # End Custom Build -!ENDIF +!ENDIF # End Source File # End Group @@ -576,10 +576,6 @@ SOURCE=..\hardware\hw_drv.h # End Source File # Begin Source File -SOURCE=..\hardware\hw_glide.h -# End Source File -# Begin Source File - SOURCE=..\hardware\hw_glob.h # End Source File # Begin Source File diff --git a/src/sdl/Srb2SDL.props b/src/sdl/Srb2SDL.props index 260f81ee..75839a5b 100644 --- a/src/sdl/Srb2SDL.props +++ b/src/sdl/Srb2SDL.props @@ -5,7 +5,10 @@ - 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;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 4e083b4c..2627c3fd 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -75,7 +75,8 @@ void *hwSym(const char *funcName,void *handle) void *funcPointer = NULL; #ifdef HWRENDER if (0 == strcmp("SetPalette", funcName)) - funcPointer = &OglSdlSetPalette; + funcPointer = &OglSdlSetPalette; + GETFUNC(Init); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); @@ -90,7 +91,6 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(DrawModel); GETFUNC(CreateModelVBOs); GETFUNC(SetTransform); - GETFUNC(GetRenderVersion); GETFUNC(PostImgRedraw); GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); @@ -100,6 +100,20 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(MakeScreenTexture); GETFUNC(MakeScreenFinalTexture); GETFUNC(DrawScreenFinalTexture); + + GETFUNC(RenderSkyDome); + + GETFUNC(LoadShaders); + GETFUNC(KillShaders); + GETFUNC(SetShader); + GETFUNC(UnSetShader); + + GETFUNC(LoadCustomShader); + GETFUNC(InitCustomShaders); + + GETFUNC(StartBatching); + GETFUNC(RenderBatches); + #else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) return funcPointer; //&FinishUpdate; diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 41a9d7cd..41874e9f 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -45,6 +45,7 @@ extern int SDL_main(int argc, char *argv[]); #ifdef LOGMESSAGES FILE *logstream = NULL; +char logfilename[1024]; #endif #ifndef DOXYGEN @@ -130,10 +131,12 @@ int main(int argc, char **argv) #ifdef LOGMESSAGES #ifdef DEFAULTDIR if (logdir) - logstream = fopen(va("%s/"DEFAULTDIR"/log.txt",logdir), "wt"); + strcpy(logfilename, va("%s/"DEFAULTDIR"/log.txt",logdir)); else #endif - logstream = fopen("./log.txt", "wt"); + strcpy(logfilename, "./log.txt"); + + logstream = fopen(logfilename, "wt"); #endif //I_OutputMsg("I_StartupSystem() ...\n"); @@ -157,6 +160,7 @@ int main(int argc, char **argv) #endif MakeCodeWritable(); #endif + // startup SRB2 CONS_Printf("Setting up SRB2Kart...\n"); D_SRB2Main(); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index ec4111f6..c630e5d8 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -102,6 +102,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #endif +#if (defined (__unix__) && !defined (_MSDOS)) || defined (UNIXCOMMON) +#include +#include +#define NEWSIGNALHANDLER +#endif + #ifndef NOMUMBLE #ifdef __linux__ // need -lrt #include @@ -247,13 +253,11 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; -FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) +static void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; const char * sigmsg; - char sigdef[32]; - - D_QuitNetGame(); // Fix server freezes + char msg[128]; switch (num) { @@ -279,20 +283,41 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) sigmsg = "SIGABRT - abnormal termination triggered by abort call"; break; default: - sprintf(sigdef,"signal number %d", num); - sigmsg = sigdef; + sprintf(msg,"signal number %d", num); + if (coredumped) + sigmsg = 0; + else + sigmsg = msg; } - I_OutputMsg("\nsignal_handler() error: %s\n", sigmsg); + if (coredumped) + { + if (sigmsg) + sprintf(msg, "%s (core dumped)", sigmsg); + else + strcat(msg, " (core dumped)"); + + sigmsg = msg; + } + + I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, - "Signal caught", + "Process killed by signal", sigmsg, NULL); +} + +#ifndef NEWSIGNALHANDLER +FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) +{ + D_QuitNetGame(); // Fix server freezes + I_ReportSignal(num, 0); I_ShutdownSystem(); signal(num, SIG_DFL); //default signal action raise(num); I_Quit(); } +#endif FUNCNORETURN static ATTRNORETURN void quit_handler(int num) { @@ -668,7 +693,7 @@ static inline void I_ShutdownConsole(void){} // // StartupKeyboard // -void I_StartupKeyboard (void) +static void I_RegisterSignals (void) { #ifdef SIGINT signal(SIGINT , quit_handler); @@ -682,10 +707,12 @@ void I_StartupKeyboard (void) // If these defines don't exist, // then compilation would have failed above us... +#ifndef NEWSIGNALHANDLER signal(SIGILL , signal_handler); signal(SIGSEGV , signal_handler); signal(SIGABRT , signal_handler); signal(SIGFPE , signal_handler); +#endif } // @@ -2961,7 +2988,7 @@ static void I_ShutdownTimer(void) pfntimeGetTime = NULL; if (winmm) { - p_timeEndPeriod pfntimeEndPeriod = (p_timeEndPeriod)GetProcAddress(winmm, "timeEndPeriod"); + p_timeEndPeriod pfntimeEndPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeEndPeriod"); if (pfntimeEndPeriod) pfntimeEndPeriod(1); FreeLibrary(winmm); @@ -3006,10 +3033,10 @@ void I_StartupTimer(void) winmm = LoadLibraryA("winmm.dll"); if (winmm) { - p_timeEndPeriod pfntimeBeginPeriod = (p_timeEndPeriod)GetProcAddress(winmm, "timeBeginPeriod"); + p_timeEndPeriod pfntimeBeginPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeBeginPeriod"); if (pfntimeBeginPeriod) pfntimeBeginPeriod(1); - pfntimeGetTime = (p_timeGetTime)GetProcAddress(winmm, "timeGetTime"); + pfntimeGetTime = (p_timeGetTime)(LPVOID)GetProcAddress(winmm, "timeGetTime"); } I_AddExitFunc(I_ShutdownTimer); #endif @@ -3023,6 +3050,85 @@ void I_Sleep(void) SDL_Delay(cv_sleep.value); } +#ifdef NEWSIGNALHANDLER +static void newsignalhandler_Warn(const char *pr) +{ + char text[128]; + + snprintf(text, sizeof text, + "Error while setting up signal reporting: %s: %s", + pr, + strerror(errno) + ); + + I_OutputMsg("%s\n", text); + + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + "Startup error", + text, NULL); + + I_ShutdownConsole(); + exit(-1); +} + +static void I_Fork(void) +{ + int child; + int status; + int signum; + int c; + + child = fork(); + + switch (child) + { + case -1: + newsignalhandler_Warn("fork()"); + break; + case 0: + break; + default: + if (logstream) + fclose(logstream);/* the child has this */ + + c = wait(&status); + +#ifdef LOGMESSAGES + /* By the way, exit closes files. */ + logstream = fopen(logfilename, "at"); +#else + logstream = 0; +#endif + + if (c == -1) + { + kill(child, SIGKILL); + newsignalhandler_Warn("wait()"); + } + else + { + if (WIFSIGNALED (status)) + { + signum = WTERMSIG (status); +#ifdef WCOREDUMP + I_ReportSignal(signum, WCOREDUMP (status)); +#else + I_ReportSignal(signum, 0); +#endif + status = 128 + signum; + } + else if (WIFEXITED (status)) + { + status = WEXITSTATUS (status); + } + + I_ShutdownConsole(); + exit(status); + } + } +} +#endif/*NEWSIGNALHANDLER*/ + INT32 I_StartupSystem(void) { SDL_version SDLcompiled; @@ -3034,6 +3140,10 @@ INT32 I_StartupSystem(void) I_AddExitFunc(I_stop_threads); #endif I_StartupConsole(); +#ifdef NEWSIGNALHANDLER + I_Fork(); +#endif + I_RegisterSignals(); I_OutputMsg("Compiled for SDL version: %d.%d.%d\n", SDLcompiled.major, SDLcompiled.minor, SDLcompiled.patch); I_OutputMsg("Linked with SDL version: %d.%d.%d\n", @@ -3276,6 +3386,10 @@ void I_ShutdownSystem(void) { INT32 c; +#ifndef NEWSIGNALHANDLER + I_ShutdownConsole(); +#endif + for (c = MAX_QUIT_FUNCS-1; c >= 0; c--) if (quit_funcs[c]) (*quit_funcs[c])(); @@ -3312,7 +3426,7 @@ void I_GetDiskFreeSpace(INT64 *freespace) if (!testwin95) { - pfnGetDiskFreeSpaceEx = (p_GetDiskFreeSpaceExA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetDiskFreeSpaceExA"); + pfnGetDiskFreeSpaceEx = (p_GetDiskFreeSpaceExA)(LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetDiskFreeSpaceExA"); testwin95 = true; } if (pfnGetDiskFreeSpaceEx) @@ -3336,7 +3450,7 @@ void I_GetDiskFreeSpace(INT64 *freespace) char *I_GetUserName(void) { - static char username[MAXPLAYERNAME]; + static char username[MAXPLAYERNAME+1]; char *p; #ifdef _WIN32 DWORD i = MAXPLAYERNAME; @@ -3832,7 +3946,7 @@ const CPUInfoFlags *I_CPUInfo(void) #if defined (_WIN32) static CPUInfoFlags WIN_CPUInfo; SYSTEM_INFO SI; - p_IsProcessorFeaturePresent pfnCPUID = (p_IsProcessorFeaturePresent)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsProcessorFeaturePresent"); + p_IsProcessorFeaturePresent pfnCPUID = (p_IsProcessorFeaturePresent)(LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsProcessorFeaturePresent"); ZeroMemory(&WIN_CPUInfo,sizeof (WIN_CPUInfo)); if (pfnCPUID) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 42e0a917..a740ef84 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -351,11 +351,6 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) case SDL_SCANCODE_RGUI: return KEY_RIGHTWIN; default: break; } -#ifdef HWRENDER - DBG_Printf("Unknown incoming scancode: %d, represented %c\n", - code, - SDL_GetKeyName(SDL_GetKeyFromScancode(code))); -#endif return 0; } @@ -635,11 +630,6 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) if (cv_usemouse.value) I_StartupMouse(); } //else firsttimeonmouse = SDL_FALSE; - - capslock = !!( SDL_GetModState() & KMOD_CAPS );// in case CL changes - - if (USE_MOUSEINPUT) - SDLdoGrabMouse(); } else if (!mousefocus && !kbfocus) { @@ -1296,6 +1286,8 @@ void I_StartupMouse(void) // void I_OsPolling(void) { + SDL_Keymod mod; + if (consolevent) I_GetConsoleEvents(); if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) @@ -1310,6 +1302,18 @@ void I_OsPolling(void) I_GetMouseEvents(); I_GetEvent(); + + mod = SDL_GetModState(); + /* Handle here so that our state is always synched with the system. */ + shiftdown = ctrldown = altdown = 0; + capslock = false; + if (mod & KMOD_LSHIFT) shiftdown |= 1; + if (mod & KMOD_RSHIFT) shiftdown |= 2; + if (mod & KMOD_LCTRL) ctrldown |= 1; + if (mod & KMOD_RCTRL) ctrldown |= 2; + if (mod & KMOD_LALT) altdown |= 1; + if (mod & KMOD_RALT) altdown |= 2; + if (mod & KMOD_CAPS) capslock = true; } // @@ -1641,6 +1645,7 @@ INT32 VID_SetMode(INT32 modeNum) //Impl_SetWindowName("SRB2Kart "VERSIONSTRING); SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); + Impl_VideoSetupBuffer(); if (rendermode == render_soft) { @@ -1649,8 +1654,6 @@ INT32 VID_SetMode(INT32 modeNum) SDL_FreeSurface(bufSurface); bufSurface = NULL; } - - Impl_VideoSetupBuffer(); } return SDL_TRUE; @@ -1773,7 +1776,7 @@ static void Impl_VideoSetupSDLBuffer(void) static void Impl_VideoSetupBuffer(void) { // Set up game's software render buffer - if (rendermode == render_soft) + //if (rendermode == render_soft) { vid.rowbytes = vid.width * vid.bpp; vid.direct = NULL; @@ -1828,9 +1831,11 @@ void I_StartupGraphics(void) framebuffer = SDL_TRUE; } if (M_CheckParm("-software")) - { rendermode = render_soft; - } +#ifdef HWRENDER + else if (M_CheckParm("-opengl")) + rendermode = render_opengl; +#endif usesdl2soft = M_CheckParm("-softblit"); borderlesswindow = M_CheckParm("-borderless"); @@ -1838,9 +1843,8 @@ void I_StartupGraphics(void) //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); VID_Command_ModeList_f(); #ifdef HWRENDER - if (M_CheckParm("-opengl") || rendermode == render_opengl) + if (rendermode == render_opengl) { - rendermode = render_opengl; HWD.pfnInit = hwSym("Init",NULL); HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); @@ -1857,7 +1861,6 @@ void I_StartupGraphics(void) HWD.pfnDrawModel = hwSym("DrawModel",NULL); HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); - HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); @@ -1867,13 +1870,22 @@ void I_StartupGraphics(void) HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - // check gl renderer lib - if (HWD.pfnGetRenderVersion() != VERSION) - I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2Kart properly.\n")); - if (!HWD.pfnInit(I_Error)) // let load the OpenGL library - { + + 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; - } } #endif diff --git a/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj b/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj index de12201f..ee0bf469 100644 --- a/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj @@ -1064,13 +1064,6 @@ path = ../../hardware/hw_drv.h; refType = 2; }; - 8417773B085A106C000C01D8 = { - fileEncoding = 30; - isa = PBXFileReference; - name = hw_glide.h; - path = ../../hardware/hw_glide.h; - refType = 2; - }; 8417773C085A106C000C01D8 = { fileEncoding = 30; isa = PBXFileReference; diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index a8ecbf7f..00930bfb 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -181,7 +181,6 @@ 1E44AE640B67CC2B00BAD059 /* hw_cache.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = hw_cache.c; path = ../../hardware/hw_cache.c; sourceTree = SOURCE_ROOT; }; 1E44AE650B67CC2B00BAD059 /* hw_dll.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_dll.h; path = ../../hardware/hw_dll.h; sourceTree = SOURCE_ROOT; }; 1E44AE660B67CC2B00BAD059 /* hw_drv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_drv.h; path = ../../hardware/hw_drv.h; sourceTree = SOURCE_ROOT; }; - 1E44AE670B67CC2B00BAD059 /* hw_glide.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_glide.h; path = ../../hardware/hw_glide.h; sourceTree = SOURCE_ROOT; }; 1E44AE680B67CC2B00BAD059 /* hw_light.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = hw_light.c; path = ../../hardware/hw_light.c; sourceTree = SOURCE_ROOT; }; 1E44AE690B67CC2B00BAD059 /* hw_light.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_light.h; path = ../../hardware/hw_light.h; sourceTree = SOURCE_ROOT; }; 1E44AE6A0B67CC2B00BAD059 /* hw3sound.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw3sound.h; path = ../../hardware/hw3sound.h; sourceTree = SOURCE_ROOT; }; @@ -535,7 +534,6 @@ 1E44AE640B67CC2B00BAD059 /* hw_cache.c */, 1E44AE650B67CC2B00BAD059 /* hw_dll.h */, 1E44AE660B67CC2B00BAD059 /* hw_drv.h */, - 1E44AE670B67CC2B00BAD059 /* hw_glide.h */, 1E44AE680B67CC2B00BAD059 /* hw_light.c */, 1E44AE690B67CC2B00BAD059 /* hw_light.h */, 1E44AE6A0B67CC2B00BAD059 /* hw3sound.h */, @@ -1219,7 +1217,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.23; + CURRENT_PROJECT_VERSION = 2.1.24; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1231,7 +1229,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.23; + CURRENT_PROJECT_VERSION = 2.1.24; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 4347b35b..b006047f 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -36,6 +36,7 @@ #ifdef HWRENDER #include "../hardware/r_opengl/r_opengl.h" +#include "../hardware/hw_main.h" #include "ogl_sdl.h" #include "../i_system.h" #include "hwsym_sdl.h" @@ -89,15 +90,15 @@ boolean LoadGL(void) const char *OGLLibname = NULL; const char *GLULibname = NULL; - if (M_CheckParm ("-OGLlib") && M_IsNextParm()) + if (M_CheckParm("-OGLlib") && M_IsNextParm()) OGLLibname = M_GetNextParm(); if (SDL_GL_LoadLibrary(OGLLibname) != 0) { - I_OutputMsg("Could not load OpenGL Library: %s\n" + CONS_Alert(CONS_ERROR, "Could not load OpenGL Library: %s\n" "Falling back to Software mode.\n", SDL_GetError()); - if (!M_CheckParm ("-OGLlib")) - I_OutputMsg("If you know what is the OpenGL library's name, use -OGLlib\n"); + if (!M_CheckParm("-OGLlib")) + CONS_Printf("If you know what is the OpenGL library's name, use -OGLlib\n"); return 0; } @@ -117,7 +118,7 @@ boolean LoadGL(void) GLULibname = NULL; #endif - if (M_CheckParm ("-GLUlib") && M_IsNextParm()) + if (M_CheckParm("-GLUlib") && M_IsNextParm()) GLULibname = M_GetNextParm(); if (GLULibname) @@ -127,15 +128,15 @@ boolean LoadGL(void) return SetupGLfunc(); else { - I_OutputMsg("Could not load GLU Library: %s\n", GLULibname); - if (!M_CheckParm ("-GLUlib")) - I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n"); + CONS_Alert(CONS_ERROR, "Could not load GLU Library: %s\n", GLULibname); + if (!M_CheckParm("-GLUlib")) + CONS_Printf("If you know what is the GLU library's name, use -GLUlib\n"); } } else { - I_OutputMsg("Could not load GLU Library\n"); - I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n"); + 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"); } #endif return SetupGLfunc(); @@ -151,31 +152,29 @@ boolean LoadGL(void) */ boolean OglSdlSurface(INT32 w, INT32 h) { - INT32 cbpp; - const GLvoid *glvendor = NULL, *glrenderer = NULL, *glversion = NULL; + INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; + static boolean first_init = false; - cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; - - glvendor = pglGetString(GL_VENDOR); - // Get info and extensions. - //BP: why don't we make it earlier ? - //Hurdler: we cannot do that before intialising gl context - glrenderer = pglGetString(GL_RENDERER); - glversion = pglGetString(GL_VERSION); - gl_extensions = pglGetString(GL_EXTENSIONS); - - DBG_Printf("Vendor : %s\n", glvendor); - DBG_Printf("Renderer : %s\n", glrenderer); - DBG_Printf("Version : %s\n", glversion); - DBG_Printf("Extensions : %s\n", gl_extensions); oglflags = 0; + if (!first_init) + { + gl_version = pglGetString(GL_VERSION); + gl_renderer = pglGetString(GL_RENDERER); + gl_extensions = pglGetString(GL_EXTENSIONS); + + GL_DBG_Printf("OpenGL %s\n", gl_version); + GL_DBG_Printf("GPU: %s\n", gl_renderer); + GL_DBG_Printf("Extensions: %s\n", gl_extensions); + } + first_init = true; + if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); else maximumAnisotropy = 1; - SetupGLFunc13(); + SetupGLFunc4(); granisotropicmode_cons_t[1].value = maximumAnisotropy; @@ -221,7 +220,7 @@ 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, RGBA_t *pgamma) { INT32 i = -1; UINT32 redgamma = pgamma->s.red, greengamma = pgamma->s.green, diff --git a/src/sdl12/Srb2SDL-vc10.vcxproj b/src/sdl12/Srb2SDL-vc10.vcxproj index 0ac7e9e5..d7f13751 100644 --- a/src/sdl12/Srb2SDL-vc10.vcxproj +++ b/src/sdl12/Srb2SDL-vc10.vcxproj @@ -1375,7 +1375,6 @@ - diff --git a/src/sdl12/Srb2SDL-vc9.vcproj b/src/sdl12/Srb2SDL-vc9.vcproj index fa386e38..9d807be2 100644 --- a/src/sdl12/Srb2SDL-vc9.vcproj +++ b/src/sdl12/Srb2SDL-vc9.vcproj @@ -2410,10 +2410,6 @@ RelativePath="..\hardware\hw_drv.h" > - - diff --git a/src/sdl12/Srb2SDL.dsp b/src/sdl12/Srb2SDL.dsp index 879113ca..ce35e2e2 100644 --- a/src/sdl12/Srb2SDL.dsp +++ b/src/sdl12/Srb2SDL.dsp @@ -7,19 +7,19 @@ CFG=Srb2SDL - 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 !MESSAGE NMAKE /f "Srb2SDL.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Srb2SDL.mak" CFG="Srb2SDL - Win32 Debug" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "Srb2SDL - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Srb2SDL - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -85,7 +85,7 @@ LINK32=link.exe # ADD LINK32 SDL.lib SDL_mixer.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /pdb:"C:\srb2demo2\srb2sdldebug.pdb" /debug /machine:I386 /out:"C:\srb2demo2\srb2sdldebug.exe" /pdbtype:sept # SUBTRACT LINK32 /pdb:none -!ENDIF +!ENDIF # Begin Target @@ -213,7 +213,7 @@ SOURCE=.\SDL_main\SDL_win32_main.c # PROP Exclude_From_Build 1 -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -274,7 +274,7 @@ InputName=tmap # End Custom Build -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -308,7 +308,7 @@ InputName=tmap_mmx # End Custom Build -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -339,7 +339,7 @@ InputName=tmap_vc # End Custom Build -!ENDIF +!ENDIF # End Source File # End Group @@ -576,10 +576,6 @@ SOURCE=..\hardware\hw_drv.h # End Source File # Begin Source File -SOURCE=..\hardware\hw_glide.h -# End Source File -# Begin Source File - SOURCE=..\hardware\hw_glob.h # End Source File # Begin Source File diff --git a/src/sdl12/hwsym_sdl.c b/src/sdl12/hwsym_sdl.c index 49340138..b6f6313f 100644 --- a/src/sdl12/hwsym_sdl.c +++ b/src/sdl12/hwsym_sdl.c @@ -49,14 +49,6 @@ #define _CREATE_DLL_ // necessary for Unix AND Windows -#ifdef HWRENDER -#include "../hardware/hw_drv.h" -#include "ogl_sdl.h" -#ifdef STATIC_OPENGL -#include "../hardware/r_opengl/r_opengl.h" -#endif -#endif - #ifdef HW3SOUND #include "../hardware/hw3dsdrv.h" #endif @@ -79,39 +71,8 @@ void *hwSym(const char *funcName,void *handle) { void *funcPointer = NULL; -#ifdef HWRENDER - if (0 == strcmp("SetPalette", funcName)) - funcPointer = &OglSdlSetPalette; - GETFUNC(Init); - GETFUNC(Draw2DLine); - GETFUNC(DrawPolygon); - GETFUNC(SetBlend); - GETFUNC(ClearBuffer); - GETFUNC(SetTexture); - GETFUNC(ReadRect); - GETFUNC(GClipRect); - GETFUNC(ClearMipMapCache); - GETFUNC(SetSpecialState); - GETFUNC(GetTextureUsed); - GETFUNC(DrawMD2); - GETFUNC(DrawMD2i); - GETFUNC(SetTransform); - GETFUNC(GetRenderVersion); -#ifdef SHUFFLE - GETFUNC(PostImgRedraw); -#endif //SHUFFLE - GETFUNC(FlushScreenTextures); - GETFUNC(StartScreenWipe); - GETFUNC(EndScreenWipe); - GETFUNC(DoScreenWipe); - GETFUNC(DrawIntermissionBG); - GETFUNC(MakeScreenTexture); - GETFUNC(MakeScreenFinalTexture); - GETFUNC(DrawScreenFinalTexture); -#else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) return funcPointer; //&FinishUpdate; -#endif //!HWRENDER #ifdef STATIC3DS GETFUNC(Startup); GETFUNC(AddSfx); diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index a2a20c61..45ce67cf 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -104,13 +104,6 @@ #include "../console.h" #include "../command.h" #include "sdlmain.h" -#ifdef HWRENDER -#include "../hardware/hw_main.h" -#include "../hardware/hw_drv.h" -// For dynamic referencing of HW rendering functions -#include "hwsym_sdl.h" -#include "ogl_sdl.h" -#endif #ifdef REMOTE_DEBUGGING #ifdef _WII @@ -169,9 +162,7 @@ static SDL_bool disable_mouse = SDL_FALSE; static INT32 firstEntry = 0; // SDL vars -#ifndef HWRENDER //[segabor] !!! I had problem compiling this source with gcc 3.3 static SDL_Surface *vidSurface = NULL; -#endif static SDL_Surface *bufSurface = NULL; static SDL_Surface *icoSurface = NULL; static SDL_Color localPalette[256]; @@ -664,11 +655,7 @@ static void VID_Command_ModeList_f(void) { #if !defined (DC) && !defined (_WIN32_WCE) && !defined (_PSP) && !defined(GP2X) INT32 i; -#ifdef HWRENDER - if (rendermode == render_opengl) - modeList = SDL_ListModes(NULL, SDL_OPENGL|SDL_FULLSCREEN); - else -#endif + modeList = SDL_ListModes(NULL, surfaceFlagsF|SDL_HWSURFACE); //Alam: At least hardware surface if (modeList == (SDL_Rect **)0 && cv_fullscreen.value) @@ -1277,11 +1264,7 @@ void I_UpdateNoBlit(void) { if (!vidSurface) return; -#ifdef HWRENDER - if (rendermode != render_soft) - OglSdlFinishUpdate(cv_vidwait.value); - else -#endif + if (vidSurface->flags&SDL_DOUBLEBUF) SDL_Flip(vidSurface); else if (exposevideo) @@ -1494,12 +1477,6 @@ void I_FinishUpdate(void) else I_OutputMsg("%s\n",SDL_GetError()); } -#ifdef HWRENDER - else - { - OglSdlFinishUpdate(cv_vidwait.value); - } -#endif exposevideo = SDL_FALSE; } @@ -1646,11 +1623,6 @@ void VID_PrepareModeList(void) firstEntry = 0; -#ifdef HWRENDER - if (rendermode == render_opengl) - modeList = SDL_ListModes(NULL, SDL_OPENGL|SDL_FULLSCREEN); - else -#endif modeList = SDL_ListModes(NULL, surfaceFlagsF|SDL_HWSURFACE); //Alam: At least hardware surface if (disable_fullscreen?0:cv_fullscreen.value) // only fullscreen needs preparation @@ -1786,23 +1758,6 @@ INT32 VID_SetMode(INT32 modeNum) I_Error("Could not set vidmode: %s\n",SDL_GetError()); } } -#ifdef HWRENDER - else // (render_soft != rendermode) - { - if (!OglSdlSurface(vid.width, vid.height, true)) - { - cv_fullscreen.value = 0; - modeNum = VID_GetModeForSize(vid.width,vid.height); - vid.width = windowedModes[modeNum][0]; - vid.height = windowedModes[modeNum][1]; - if (!OglSdlSurface(vid.width, vid.height,false)) - I_Error("Could not set vidmode: %s\n",SDL_GetError()); - } - - realwidth = (Uint16)vid.width; - realheight = (Uint16)vid.height; - } -#endif } else //(cv_fullscreen.value) { @@ -1815,15 +1770,6 @@ INT32 VID_SetMode(INT32 modeNum) if (!vidSurface) I_Error("Could not set vidmode: %s\n",SDL_GetError()); } -#ifdef HWRENDER - else //(render_soft != rendermode) - { - if (!OglSdlSurface(vid.width, vid.height, false)) - I_Error("Could not set vidmode: %s\n",SDL_GetError()); - realwidth = (Uint16)vid.width; - realheight = (Uint16)vid.height; - } -#endif } vid.modenum = VID_GetModeForSize(vidSurface->w,vidSurface->h); @@ -1950,92 +1896,31 @@ void I_StartupGraphics(void) //DisableAero(); //also disable Aero on Vista #endif -#ifdef HWRENDER - if (M_CheckParm("-opengl") || rendermode == render_opengl) - { - 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.pfnDrawMD2 = hwSym("DrawMD2",NULL); - HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL); - HWD.pfnSetTransform = hwSym("SetTransform",NULL); - HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); -#ifdef SHUFFLE - HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); -#endif - 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); - // check gl renderer lib - if (HWD.pfnGetRenderVersion() != VERSION) - I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n")); -#if 1 //#ifdef _WIN32_WCE - vid.width = BASEVIDWIDTH; - vid.height = BASEVIDHEIGHT; -#else - vid.width = 640; // hack to make voodoo cards work in 640x480 - vid.height = 480; -#endif - if (HWD.pfnInit(I_Error)) // let load the OpenGL library - { - /* - * We want at least 1 bit R, G, and B, - * and at least 16 bpp. Why 1 bit? May be more? - */ - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 1); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 1); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 1); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - if (!OglSdlSurface(vid.width, vid.height, (USE_FULLSCREEN))) - if (!OglSdlSurface(vid.width, vid.height, !(USE_FULLSCREEN))) - rendermode = render_soft; - } - else - rendermode = render_soft; - } -#else rendermode = render_soft; //force software mode when there no HWRENDER code -#endif - if (render_soft == rendermode) - { #if defined(_WII) - vid.width = 640; - vid.height = 480; + vid.width = 640; + vid.height = 480; #elif defined(_PS3) - vid.width = 720; - vid.height = 480; + vid.width = 720; + vid.height = 480; #else - vid.width = BASEVIDWIDTH; - vid.height = BASEVIDHEIGHT; + vid.width = BASEVIDWIDTH; + vid.height = BASEVIDHEIGHT; #endif - SDLSetMode(vid.width, vid.height, BitsPerPixel, surfaceFlagsW); - if (!vidSurface) - { - CONS_Printf(M_GetText("Could not set vidmode: %s\n") ,SDL_GetError()); - vid.rowbytes = 0; - graphics_started = true; - return; - } - vid.rowbytes = vid.width * vid.bpp; - vid.direct = SDLGetDirect(); - vid.buffer = malloc(vid.rowbytes*vid.height*NUMSCREENS); - if (vid.buffer) memset(vid.buffer,0x00,vid.rowbytes*vid.height*NUMSCREENS); - else CONS_Printf("%s", M_GetText("Not enough memory for video buffer\n")); + SDLSetMode(vid.width, vid.height, BitsPerPixel, surfaceFlagsW); + if (!vidSurface) + { + CONS_Printf(M_GetText("Could not set vidmode: %s\n") ,SDL_GetError()); + vid.rowbytes = 0; + graphics_started = true; + return; } + vid.rowbytes = vid.width * vid.bpp; + vid.direct = SDLGetDirect(); + vid.buffer = malloc(vid.rowbytes*vid.height*NUMSCREENS); + if (vid.buffer) memset(vid.buffer,0x00,vid.rowbytes*vid.height*NUMSCREENS); + else CONS_Printf("%s", M_GetText("Not enough memory for video buffer\n")); + if (M_CheckParm("-nomousegrab")) mousegrabok = SDL_FALSE; #ifdef _DEBUG @@ -2091,10 +1976,6 @@ void I_ShutdownGraphics(void) #endif graphics_started = false; CONS_Printf("%s", M_GetText("shut down\n")); -#ifdef HWRENDER - if (GLUhandle) - hwClose(GLUhandle); -#endif #ifndef _arch_dreamcast SDL_QuitSubSystem(SDL_INIT_VIDEO); #endif diff --git a/src/sdl12/macosx/Srb2mac.pbproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.pbproj/project.pbxproj index 1f8e3276..1fe2ea2d 100644 --- a/src/sdl12/macosx/Srb2mac.pbproj/project.pbxproj +++ b/src/sdl12/macosx/Srb2mac.pbproj/project.pbxproj @@ -1064,13 +1064,6 @@ path = ../../hardware/hw_drv.h; refType = 2; }; - 8417773B085A106C000C01D8 = { - fileEncoding = 30; - isa = PBXFileReference; - name = hw_glide.h; - path = ../../hardware/hw_glide.h; - refType = 2; - }; 8417773C085A106C000C01D8 = { fileEncoding = 30; isa = PBXFileReference; diff --git a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj index 69c544c5..9b9d33b7 100644 --- a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -181,7 +181,6 @@ 1E44AE640B67CC2B00BAD059 /* hw_cache.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = hw_cache.c; path = ../../hardware/hw_cache.c; sourceTree = SOURCE_ROOT; }; 1E44AE650B67CC2B00BAD059 /* hw_dll.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_dll.h; path = ../../hardware/hw_dll.h; sourceTree = SOURCE_ROOT; }; 1E44AE660B67CC2B00BAD059 /* hw_drv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_drv.h; path = ../../hardware/hw_drv.h; sourceTree = SOURCE_ROOT; }; - 1E44AE670B67CC2B00BAD059 /* hw_glide.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_glide.h; path = ../../hardware/hw_glide.h; sourceTree = SOURCE_ROOT; }; 1E44AE680B67CC2B00BAD059 /* hw_light.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = hw_light.c; path = ../../hardware/hw_light.c; sourceTree = SOURCE_ROOT; }; 1E44AE690B67CC2B00BAD059 /* hw_light.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_light.h; path = ../../hardware/hw_light.h; sourceTree = SOURCE_ROOT; }; 1E44AE6A0B67CC2B00BAD059 /* hw3sound.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw3sound.h; path = ../../hardware/hw3sound.h; sourceTree = SOURCE_ROOT; }; @@ -535,7 +534,6 @@ 1E44AE640B67CC2B00BAD059 /* hw_cache.c */, 1E44AE650B67CC2B00BAD059 /* hw_dll.h */, 1E44AE660B67CC2B00BAD059 /* hw_drv.h */, - 1E44AE670B67CC2B00BAD059 /* hw_glide.h */, 1E44AE680B67CC2B00BAD059 /* hw_light.c */, 1E44AE690B67CC2B00BAD059 /* hw_light.h */, 1E44AE6A0B67CC2B00BAD059 /* hw3sound.h */, @@ -1219,7 +1217,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.23; + CURRENT_PROJECT_VERSION = 2.1.24; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1231,7 +1229,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.23; + CURRENT_PROJECT_VERSION = 2.1.24; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sdl12/ogl_sdl.c b/src/sdl12/ogl_sdl.c deleted file mode 100644 index eb7e9996..00000000 --- a/src/sdl12/ogl_sdl.c +++ /dev/null @@ -1,317 +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 SDL specific part of the OpenGL API for SRB2 - -#ifdef _MSC_VER -#pragma warning(disable : 4214 4244) -#endif - -#ifdef HAVE_SDL - -#include "SDL.h" - -#ifdef _MSC_VER -#pragma warning(default : 4214 4244) -#endif - -#include "../doomdef.h" - -#ifdef HWRENDER -#include "../hardware/r_opengl/r_opengl.h" -#include "ogl_sdl.h" -#include "../i_system.h" -#include "hwsym_sdl.h" -#include "../m_argv.h" - -#ifdef DEBUG_TO_FILE -#include -#if defined (_WIN32) && !defined (__CYGWIN__) -#include -#else -#include -#endif -#include -#include -#endif - -#ifdef USE_WGL_SWAP -PFNWGLEXTSWAPCONTROLPROC wglSwapIntervalEXT = NULL; -#else -typedef int (*PFNGLXSWAPINTERVALPROC) (int); -PFNGLXSWAPINTERVALPROC glXSwapIntervalSGIEXT = NULL; -#endif - -#ifndef STATIC_OPENGL -PFNglClear pglClear; -PFNglGetIntegerv pglGetIntegerv; -PFNglGetString pglGetString; -#endif - -#ifdef _PSP -static const Uint32 WOGLFlags = SDL_HWSURFACE|SDL_OPENGL/*|SDL_RESIZABLE*/; -static const Uint32 FOGLFlags = SDL_HWSURFACE|SDL_OPENGL|SDL_FULLSCREEN; -#else -static const Uint32 WOGLFlags = SDL_OPENGL/*|SDL_RESIZABLE*/; -static const Uint32 FOGLFlags = SDL_OPENGL|SDL_FULLSCREEN; -#endif - -/** \brief SDL video display surface -*/ -SDL_Surface *vidSurface = NULL; -INT32 oglflags = 0; -void *GLUhandle = NULL; - -#ifndef STATIC_OPENGL -void *GetGLFunc(const char *proc) -{ - if (strncmp(proc, "glu", 3) == 0) - { - if (GLUhandle) - return hwSym(proc, GLUhandle); - else - return NULL; - } - return SDL_GL_GetProcAddress(proc); -} -#endif - -boolean LoadGL(void) -{ -#ifndef STATIC_OPENGL - const char *OGLLibname = NULL; - const char *GLULibname = NULL; - - if (M_CheckParm ("-OGLlib") && M_IsNextParm()) - OGLLibname = M_GetNextParm(); - - if (SDL_GL_LoadLibrary(OGLLibname) != 0) - { - I_OutputMsg("Could not load OpenGL Library: %s\n" - "Falling back to Software mode.\n", SDL_GetError()); - if (!M_CheckParm ("-OGLlib")) - I_OutputMsg("If you know what is the OpenGL library's name, use -OGLlib\n"); - return 0; - } - -#if 0 - GLULibname = "/proc/self/exe"; -#elif defined (_WIN32) - GLULibname = "GLU32.DLL"; -#elif defined (__MACH__) - GLULibname = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"; -#elif defined (macintos) - GLULibname = "OpenGLLibrary"; -#elif defined (__unix__) - GLULibname = "libGLU.so.1"; -#elif defined (__HAIKU__) - GLULibname = "libGLU.so"; -#else - GLULibname = NULL; -#endif - - if (M_CheckParm ("-GLUlib") && M_IsNextParm()) - GLULibname = M_GetNextParm(); - - if (GLULibname) - { - GLUhandle = hwOpen(GLULibname); - if (GLUhandle) - return SetupGLfunc(); - else - { - I_OutputMsg("Could not load GLU Library: %s\n", GLULibname); - if (!M_CheckParm ("-GLUlib")) - I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n"); - } - } - else - { - I_OutputMsg("Could not load GLU Library\n"); - I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n"); - } -#endif - return SetupGLfunc(); -} - -/** \brief The OglSdlSurface function - - \param w width - \param h height - \param isFullscreen if true, go fullscreen - - \return if true, changed video mode -*/ -boolean OglSdlSurface(INT32 w, INT32 h, boolean isFullscreen) -{ - INT32 cbpp; - Uint32 OGLFlags; - const GLvoid *glvendor = NULL, *glrenderer = NULL, *glversion = NULL; - - cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; - - if (vidSurface) - { - //Alam: SDL_Video system free vidSurface for me -#ifdef VOODOOSAFESWITCHING - SDL_QuitSubSystem(SDL_INIT_VIDEO); - SDL_InitSubSystem(SDL_INIT_VIDEO); -#endif - } - - if (isFullscreen) - OGLFlags = FOGLFlags; - else - OGLFlags = WOGLFlags; - - cbpp = SDL_VideoModeOK(w, h, cbpp, OGLFlags); - if (cbpp < 16) - return true; //Alam: Let just say we did, ok? - - vidSurface = SDL_SetVideoMode(w, h, cbpp, OGLFlags); - if (!vidSurface) - return false; - - glvendor = pglGetString(GL_VENDOR); - // Get info and extensions. - //BP: why don't we make it earlier ? - //Hurdler: we cannot do that before intialising gl context - glrenderer = pglGetString(GL_RENDERER); - glversion = pglGetString(GL_VERSION); - gl_extensions = pglGetString(GL_EXTENSIONS); - - DBG_Printf("Vendor : %s\n", glvendor); - DBG_Printf("Renderer : %s\n", glrenderer); - DBG_Printf("Version : %s\n", glversion); - DBG_Printf("Extensions : %s\n", gl_extensions); - oglflags = 0; - -#ifdef _WIN32 - // 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(glrenderer, "810")) oglflags |= GLF_NOZBUFREAD; -#elif defined (unix) || defined (UNIXCOMMON) - // disable advanced features not working on somes hardware - if (strstr(glrenderer, "G200")) oglflags |= GLF_NOTEXENV; - if (strstr(glrenderer, "G400")) oglflags |= GLF_NOTEXENV; -#endif - DBG_Printf("oglflags : 0x%X\n", oglflags ); - -#ifdef USE_PALETTED_TEXTURE - if (isExtAvailable("GL_EXT_paletted_texture", gl_extensions)) - glColorTableEXT = SDL_GL_GetProcAddress("glColorTableEXT"); - else - glColorTableEXT = NULL; -#endif - -#ifdef USE_WGL_SWAP - if (isExtAvailable("WGL_EXT_swap_control", gl_extensions)) - wglSwapIntervalEXT = SDL_GL_GetProcAddress("wglSwapIntervalEXT"); - else - wglSwapIntervalEXT = NULL; -#else - if (isExtAvailable("GLX_SGI_swap_control", gl_extensions)) - glXSwapIntervalSGIEXT = SDL_GL_GetProcAddress("glXSwapIntervalSGI"); - else - glXSwapIntervalSGIEXT = NULL; -#endif - -#ifndef KOS_GL_COMPATIBILITY - if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) - pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); - else -#endif - maximumAnisotropy = 0; - - SetupGLFunc13(); - - granisotropicmode_cons_t[1].value = maximumAnisotropy; - - SetModelView(w, h); - SetStates(); - pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - HWR_Startup(); -#ifdef KOS_GL_COMPATIBILITY - textureformatGL = GL_ARGB4444; -#else - textureformatGL = cbpp > 16 ? GL_RGBA : GL_RGB5_A1; -#endif - - return true; -} - -/** \brief The OglSdlFinishUpdate function - - \param vidwait wait for video sync - - \return void -*/ -void OglSdlFinishUpdate(boolean waitvbl) -{ - static boolean oldwaitvbl = false; - if (oldwaitvbl != waitvbl) - { -#ifdef USE_WGL_SWAP - if (wglSwapIntervalEXT) - wglSwapIntervalEXT(waitvbl); -#else - if (glXSwapIntervalSGIEXT) - glXSwapIntervalSGIEXT(waitvbl); -#endif - } - oldwaitvbl = waitvbl; - - SDL_GL_SwapBuffers(); -} - -EXPORT void HWRAPI( OglSdlSetPalette) (RGBA_t *palette, RGBA_t *pgamma) -{ - INT32 i = -1; - UINT32 redgamma = pgamma->s.red, greengamma = pgamma->s.green, - bluegamma = pgamma->s.blue; - -#if 0 // changing the gamma to 127 is a bad idea - i = SDL_SetGamma(byteasfloat(redgamma), byteasfloat(greengamma), byteasfloat(bluegamma)); -#endif - if (i == 0) redgamma = greengamma = bluegamma = 0x7F; //Alam: cool - for (i = 0; i < 256; i++) - { - 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; - } -#ifdef USE_PALETTED_TEXTURE - if (glColorTableEXT) - { - for (i = 0; i < 256; i++) - { - palette_tex[(3*i)+0] = palette[i].s.red; - palette_tex[(3*i)+1] = palette[i].s.green; - palette_tex[(3*i)+2] = palette[i].s.blue; - } - glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex); - } -#endif - // on a chang�de palette, il faut recharger toutes les textures - // jaja, und noch viel mehr ;-) - Flush(); -} - -#endif //HWRENDER -#endif //SDL diff --git a/src/sdl12/ogl_sdl.h b/src/sdl12/ogl_sdl.h deleted file mode 100644 index 43c28fa4..00000000 --- a/src/sdl12/ogl_sdl.h +++ /dev/null @@ -1,30 +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 SDL specific part of the OpenGL API for SRB2 - -#include "../v_video.h" - -extern SDL_Surface *vidSurface; -extern void *GLUhandle; - -boolean OglSdlSurface(INT32 w, INT32 h, boolean isFullscreen); - -void OglSdlFinishUpdate(boolean vidwait); - -#ifdef _CREATE_DLL_ -EXPORT void HWRAPI( OglSdlSetPalette ) (RGBA_t *palette, RGBA_t *pgamma); -#endif diff --git a/src/sounds.h b/src/sounds.h index bb46ea9d..dfd0bbdc 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -54,7 +54,7 @@ typedef enum } skinsound_t; // free sfx for S_AddSoundFx() -#define NUMSFXFREESLOTS 800 // Matches SOC Editor. +#define NUMSFXFREESLOTS 1600 // Matches SOC Editor. #define NUMSKINSFXSLOTS (MAXSKINS*NUMSKINSOUNDS) // diff --git a/src/st_stuff.c b/src/st_stuff.c index 50bac3ee..008a1461 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -203,7 +203,7 @@ void ST_Ticker(void) } // 0 is default, any others are special palettes. -static INT32 st_palette = 0; +INT32 st_palette = 0; void ST_doPaletteStuff(void) { @@ -614,9 +614,7 @@ static void ST_drawDebugInfo(void) } if (cv_debug & DBG_MEMORY) - { V_DrawRightAlignedString(320, height, V_MONOSPACE, va("Heap used: %7sKB", sizeu1(Z_TagsUsage(0, INT32_MAX)>>10))); - } } /* @@ -1834,7 +1832,7 @@ static void ST_overlayDrawer(void) { patch_t *p; - if (countdown == 1) + if (racecountdown == 1) p = timeover; else p = sboover; @@ -1954,7 +1952,7 @@ static void ST_overlayDrawer(void) if (!hu_showscores && netgame && !mapreset) { - /*if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1) + /*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)) @@ -2039,8 +2037,6 @@ static void ST_overlayDrawer(void) break; } } - - ST_drawDebugInfo(); } void ST_DrawDemoTitleEntry(void) @@ -2142,4 +2138,5 @@ void ST_Drawer(void) else V_DrawFadeScreen(120, 15-timeinmap); // Then gradually fade out from there } + ST_drawDebugInfo(); } diff --git a/src/st_stuff.h b/src/st_stuff.h index 16f7b881..5ed5dd1c 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -61,6 +61,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 lumpnum_t st_borderpatchnum; // patches, also used in intermission diff --git a/src/v_video.c b/src/v_video.c index 9233eda4..47fe4c8e 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -27,7 +27,7 @@ #include "doomstat.h" #ifdef HWRENDER -#include "hardware/hw_glob.h" +#include "hardware/hw_main.h" #endif // Each screen is [vid.width*vid.height]; @@ -58,30 +58,25 @@ static void CV_Gammaxxx_ONChange(void); // - 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 grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}}; +static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Off"}, {1, "Standard"}, {2, "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_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, 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}; -#ifdef ALAM_LIGHTING -consvar_t cv_grdynamiclighting = {"gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grstaticlighting = {"gr_staticlighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grcoronas = {"gr_coronas", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif //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 const UINT8 gammatable[5][256] = @@ -350,7 +345,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Why? - if (rendermode != render_soft) + if (rendermode == render_opengl) { HWR_DrawFixedPatch((GLPatch_t *)patch, x, y, pscale, scrn, colormap); return; @@ -572,8 +567,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ return; #ifdef HWRENDER - // Done - if (rendermode != render_soft && !con_startup) + if (rendermode == render_opengl) { HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); return; @@ -719,61 +713,6 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const } } -static void V_BlitScaledPic(INT32 px1, INT32 py1, INT32 scrn, pic_t *pic); -// Draw a linear pic, scaled, TOTALLY CRAP CODE!!! OPTIMISE AND ASM!! -// -void V_DrawScaledPic(INT32 rx1, INT32 ry1, INT32 scrn, INT32 lumpnum) -{ -#ifdef HWRENDER - if (rendermode != render_soft) - { - HWR_DrawPic(rx1, ry1, lumpnum); - return; - } -#endif - - V_BlitScaledPic(rx1, ry1, scrn, W_CacheLumpNum(lumpnum, PU_CACHE)); -} - -static void V_BlitScaledPic(INT32 rx1, INT32 ry1, INT32 scrn, pic_t * pic) -{ - INT32 dupx, dupy; - INT32 x, y; - UINT8 *src, *dest; - INT32 width, height; - - width = SHORT(pic->width); - height = SHORT(pic->height); - scrn &= V_PARAMMASK; - - if (pic->mode != 0) - { - CONS_Debug(DBG_RENDER, "pic mode %d not supported in Software\n", pic->mode); - return; - } - - dest = screens[scrn] + max(0, ry1 * vid.width) + max(0, rx1); - // y cliping to the screen - if (ry1 + height * vid.dupy >= vid.width) - height = (vid.width - ry1) / vid.dupy - 1; - // WARNING no x clipping (not needed for the moment) - - for (y = max(0, -ry1 / vid.dupy); y < height; y++) - { - for (dupy = vid.dupy; dupy; dupy--) - { - src = pic->data + y * width; - for (x = 0; x < width; x++) - { - for (dupx = vid.dupx; dupx; dupx--) - *dest++ = *src; - src++; - } - dest += vid.width - vid.dupx * width; - } - } -} - // // Fills a box of pixels with a single color, NOTE: scaled to screen size // @@ -786,7 +725,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) return; #ifdef HWRENDER - if (rendermode != render_soft && !con_startup) + if (rendermode == render_opengl) { HWR_DrawFill(x, y, w, h, c); return; @@ -906,7 +845,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) return; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + 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. @@ -1117,7 +1056,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum) size_t size, lflatsize, flatshift; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { HWR_DrawFlatFill(x, y, w, h, flatnum); return; @@ -1317,7 +1256,7 @@ void V_DrawFadeConsBack(INT32 plines) UINT8 *deststop, *buf; #ifdef HWRENDER // not win32 only 19990829 by Kin - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { UINT32 hwcolor = V_GetHWConsBackColor(); HWR_DrawConsoleBack(hwcolor, plines); @@ -2423,8 +2362,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param) INT32 yoffset, xoffset; #ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft) return; #endif @@ -2593,6 +2531,29 @@ Unoptimized version #endif } +// Taken from my videos-in-SRB2 project +// Generates a color look-up table +// which has up to 64 colors at each channel +// (see the defines in v_video.h) + +UINT8 colorlookup[CLUTSIZE][CLUTSIZE][CLUTSIZE]; + +void InitColorLUT(void) +{ + UINT8 r, g, b; + static boolean clutinit = false; + static RGBA_t *lastpalette = NULL; + if ((!clutinit) || (lastpalette != pLocalPalette)) + { + for (r = 0; r < CLUTSIZE; r++) + for (g = 0; g < CLUTSIZE; g++) + for (b = 0; b < CLUTSIZE; b++) + colorlookup[r][g][b] = NearestColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS); + clutinit = true; + lastpalette = pLocalPalette; + } +} + // V_Init // old software stuff, buffers are allocated at video mode setup // here we set the screens[x] pointers accordingly @@ -2604,13 +2565,9 @@ void V_Init(void) const INT32 screensize = vid.rowbytes * vid.height; LoadMapPalette(); - // hardware modes do not use screens[] pointers + for (i = 0; i < NUMSCREENS; i++) screens[i] = NULL; - if (rendermode != render_soft) - { - return; // be sure to cause a NULL read/write error so we detect it, in case of.. - } // start address of NUMSCREENS * width*height vidbuffers if (base) diff --git a/src/v_video.h b/src/v_video.h index c8485c17..17028a07 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -33,6 +33,18 @@ extern consvar_t cv_ticrate, cv_usegamma, cv_allcaps, cv_constextsize; // Allocates buffer screens, call before R_Init. void V_Init(void); +// Taken from my videos-in-SRB2 project +// Generates a color look-up table +// which has up to 64 colors at each channel + +#define COLORBITS 6 +#define SHIFTCOLORBITS (8-COLORBITS) +#define CLUTSIZE (1<type == RET_PK3)); +#endif + // 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) { @@ -1480,22 +1485,22 @@ static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) grPatch = HWR_GetCachedGLPatchPwad(wad, lump); - if (grPatch->mipmap.grInfo.data) + if (grPatch->mipmap->grInfo.data) { if (tag == PU_CACHE) tag = PU_HWRCACHE; - Z_ChangeTag(grPatch->mipmap.grInfo.data, tag); + Z_ChangeTag(grPatch->mipmap->grInfo.data, tag); } else { patch_t *ptr = NULL; // Only load the patch if we haven't initialised the grPatch yet - if (grPatch->mipmap.width == 0) + if (grPatch->mipmap->width == 0) ptr = W_CacheLumpNumPwad(grPatch->wadnum, grPatch->lumpnum, PU_STATIC); // Run HWR_MakePatch in all cases, to recalculate some things - HWR_MakePatch(ptr, grPatch, &grPatch->mipmap, false); + HWR_MakePatch(ptr, grPatch, grPatch->mipmap, false); Z_Free(ptr); } @@ -1532,6 +1537,7 @@ void *W_CachePatchName(const char *name, INT32 tag) return W_CachePatchNum(W_GetNumForName("MISSING"), tag); return W_CachePatchNum(num, tag); } + #ifndef NOMD5 /** @@ -1720,11 +1726,14 @@ int W_VerifyNMUSlumps(const char *filename) {"RRINGS", 6}, // Rings HUD (not named as SBO) {"YB_", 3}, // Intermission graphics, goes with the above {"M_", 2}, // As does menu stuff - {"MKFNT", 5}, // Kart font changes {"K_", 2}, // Kart graphic changes {"MUSICDEF", 8}, // Kart song definitions +#ifdef HWRENDER + {"SHADERS", 7}, + {"SH_", 3}, +#endif {NULL, 0}, }; return W_VerifyFile(filename, NMUSlist, false); diff --git a/src/w_wad.h b/src/w_wad.h index 762d3708..ffe63e79 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -77,8 +77,9 @@ typedef struct // ========================================================================= #define MAX_WADPATH 512 -#define MAX_WADFILES 48 // maximum of wad files used at the same time -// (there is a max of simultaneous open files anyway, and this should be plenty) +#define MAX_WADFILES 127 // maximum of wad files used at the same time +// Replay code relies on it being an UINT8 and, just to be safe, in case some wad counter somewhere is a SINT8, you should NOT go above 127 here if you're lazy like me. +// Besides, are there truly 127 wads worth your interrest? #define lumpcache_t void * diff --git a/src/win32/CMakeLists.txt b/src/win32/CMakeLists.txt index 39b01588..71ce88d0 100644 --- a/src/win32/CMakeLists.txt +++ b/src/win32/CMakeLists.txt @@ -1,10 +1,5 @@ file(GLOB SRB2_WIN_SOURCES *.c *.h *.rc) -if(${SRB2_CONFIG_HWRENDER}) - set(SRB2_WIN_SOURCES ${SRB2_WIN_SOURCES} ${SRB2_HWRENDER_SOURCES} ${SRB2_HWRENDER_HEADERS}) - set(SRB2_WIN_SOURCES ${SRB2_WIN_SOURCES} ${SRB2_R_OPENGL_SOURCES} ${SRB2_R_OPENGL_HEADERS}) -endif() - add_executable(SRB2DD EXCLUDE_FROM_ALL WIN32 ${SRB2_WIN_SOURCES} ) diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index 46b103df..583a3c79 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -36,10 +36,6 @@ ifndef GCC44 #OPTS+=-mms-bitfields endif -ifndef MINGW64 - OPTS+=-gdwarf-2 -endif - ifndef SDL OPTS+=-D_WINDOWS endif diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index ced3d128..65500d9b 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -91,6 +91,7 @@ + @@ -222,19 +223,6 @@ - - - - - - - - - - - - - @@ -388,20 +376,6 @@ - - - - - - - - - - - - - - @@ -502,4 +476,4 @@ - \ No newline at end of file + diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index 8f607796..e5401d72 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -87,30 +87,6 @@ Win32app - - Hw_Hardware - - - Hw_Hardware - - - Hw_Hardware - - - Hw_Hardware - - - Hw_Hardware - - - Hw_Hardware - - - Hw_Hardware - - - Hw_Hardware - Hw_Hardware @@ -480,45 +456,6 @@ 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 - Hw_Hardware @@ -897,4 +834,4 @@ A_Asm - \ No newline at end of file + diff --git a/src/win32/Srb2win-vc9.vcproj b/src/win32/Srb2win-vc9.vcproj index a64b8638..cac081ad 100644 --- a/src/win32/Srb2win-vc9.vcproj +++ b/src/win32/Srb2win-vc9.vcproj @@ -2151,10 +2151,6 @@ RelativePath="..\hardware\hw_drv.h" > - - diff --git a/src/win32/Srb2win.dsp b/src/win32/Srb2win.dsp index 501bd26b..c52873f7 100644 --- a/src/win32/Srb2win.dsp +++ b/src/win32/Srb2win.dsp @@ -7,19 +7,19 @@ CFG=Srb2win - 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 !MESSAGE NMAKE /f "Srb2win.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Srb2win.mak" CFG="Srb2win - Win32 Debug" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "Srb2win - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "Srb2win - Win32 Debug" (based on "Win32 (x86) Application") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -84,7 +84,7 @@ LINK32=link.exe # ADD LINK32 dxguid.lib user32.lib gdi32.lib winmm.lib advapi32.lib ws2_32.lib dinput.lib /nologo /subsystem:windows /profile /debug /machine:I386 /out:"C:\srb2demo2\srb2debug.exe" # SUBTRACT LINK32 /nodefaultlib -!ENDIF +!ENDIF # Begin Target @@ -148,7 +148,7 @@ SOURCE=.\Srb2win.rc !ELSEIF "$(CFG)" == "Srb2win - Win32 Debug" -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -233,7 +233,7 @@ InputName=tmap # End Custom Build -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -266,7 +266,7 @@ InputName=tmap_mmx # End Custom Build -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -298,7 +298,7 @@ InputName=tmap_vc # End Custom Build -!ENDIF +!ENDIF # End Source File # End Group @@ -535,10 +535,6 @@ SOURCE=..\hardware\hw_drv.h # End Source File # Begin Source File -SOURCE=..\hardware\hw_glide.h -# End Source File -# Begin Source File - SOURCE=..\hardware\hw_glob.h # End Source File # Begin Source File diff --git a/src/win32/Srb2win.props b/src/win32/Srb2win.props index 44a30d50..fa152f0c 100644 --- a/src/win32/Srb2win.props +++ b/src/win32/Srb2win.props @@ -5,7 +5,10 @@ - _WINDOWS;%(PreprocessorDefinitions) + + HAVE_ZLIB;HAVE_LIBGME;_WINDOWS;%(PreprocessorDefinitions) + + _WINDOWS;%(PreprocessorDefinitions) diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index b60ba750..d7a26dc8 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -1,3 +1,5 @@ +#include + //Microsoft Developer Studio generated resource script. // #include "resource.h" @@ -21,6 +23,16 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32*/ +#ifndef RT_MANIFEST +#define RT_MANIFEST 24 +#endif + +#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID +#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 +#endif + +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST srb2kart.exe.manifest + ///////////////////////////////////////////////////////////////////////////// // // Icon diff --git a/src/win32/fabdxlib.c b/src/win32/fabdxlib.c index c19b036a..45ec5d0d 100644 --- a/src/win32/fabdxlib.c +++ b/src/win32/fabdxlib.c @@ -147,7 +147,7 @@ static inline BOOL LoadDirectDraw(VOID) DDrawDLL = LoadLibraryA("DDRAW.DLL"); if (DDrawDLL == NULL) return false; - pfnDirectDrawCreate = (DDCreate)GetProcAddress(DDrawDLL, "DirectDrawCreate"); + pfnDirectDrawCreate = (DDCreate)(LPVOID)GetProcAddress(DDrawDLL, "DirectDrawCreate"); if (pfnDirectDrawCreate == NULL) return false; return true; diff --git a/src/win32/srb2kart.exe.manifest b/src/win32/srb2kart.exe.manifest new file mode 100644 index 00000000..d3b8355c --- /dev/null +++ b/src/win32/srb2kart.exe.manifest @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index bc67f04a..77ddc6e3 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -17,9 +17,6 @@ /// \brief load and initialise the 3D driver DLL #include "../doomdef.h" -#ifdef HWRENDER -#include "../hardware/hw_drv.h" // get the standard 3D Driver DLL exports prototypes -#endif #ifdef HW3SOUND #include "../hardware/hw3dsdrv.h" // get the 3D sound driver DLL export prototypes @@ -30,7 +27,7 @@ #include "win_dll.h" #include "win_main.h" // I_ShowLastError() -#if defined(HWRENDER) || defined(HW3SOUND) +#if defined(HW3SOUND) typedef struct loadfunc_s { LPCSTR fnName; LPVOID fnPointer; @@ -84,92 +81,6 @@ 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@8", &hwdriver.pfnSetPalette}, - {"FinishUpdate@4", &hwdriver.pfnFinishUpdate}, - {"Draw2DLine@12", &hwdriver.pfnDraw2DLine}, - {"DrawPolygon@16", &hwdriver.pfnDrawPolygon}, - {"SetBlend@4", &hwdriver.pfnSetBlend}, - {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, - {"SetTexture@4", &hwdriver.pfnSetTexture}, - {"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@4", &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}, - {"SetBlend", &hwdriver.pfnSetBlend}, - {"ClearBuffer", &hwdriver.pfnClearBuffer}, - {"SetTexture", &hwdriver.pfnSetTexture}, - {"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_dll.h b/src/win32/win_dll.h index b4b25958..f69a8c21 100644 --- a/src/win32/win_dll.h +++ b/src/win32/win_dll.h @@ -20,11 +20,6 @@ #define RPC_NO_WINDOWS_H #include -#ifdef HWRENDER -BOOL Init3DDriver (LPCSTR dllName); -VOID Shutdown3DDriver (VOID); -#endif - #ifdef HW3SOUND BOOL Init3DSDriver(LPCSTR dllName); VOID Shutdown3DSDriver(VOID); diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index a98aa861..b32ee617 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -3395,7 +3395,7 @@ BOOL LoadDirectInput(VOID) DInputDLL = LoadLibraryA("DINPUT.DLL"); if (DInputDLL == NULL) return false; - pfnDirectInputCreateA = (DICreateA)GetProcAddress(DInputDLL, "DirectInputCreateA"); + pfnDirectInputCreateA = (DICreateA)(LPVOID)GetProcAddress(DInputDLL, "DirectInputCreateA"); if (pfnDirectInputCreateA == NULL) return false; return true; @@ -3529,7 +3529,7 @@ void I_GetDiskFreeSpace(INT64* freespace) if (!testwin95) { - pfnGetDiskFreeSpaceEx = (p_GetDiskFreeSpaceExA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetDiskFreeSpaceExA"); + pfnGetDiskFreeSpaceEx = (p_GetDiskFreeSpaceExA)(LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetDiskFreeSpaceExA"); testwin95 = true; } if (pfnGetDiskFreeSpaceEx) @@ -3615,7 +3615,7 @@ const CPUInfoFlags *I_CPUInfo(void) { static CPUInfoFlags WIN_CPUInfo; SYSTEM_INFO SI; - p_IsProcessorFeaturePresent pfnCPUID = (p_IsProcessorFeaturePresent)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsProcessorFeaturePresent"); + p_IsProcessorFeaturePresent pfnCPUID = (p_IsProcessorFeaturePresent)(LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsProcessorFeaturePresent"); ZeroMemory(&WIN_CPUInfo,sizeof (WIN_CPUInfo)); if (pfnCPUID) @@ -3658,9 +3658,9 @@ static p_SetProcessAffinityMask pfnSetProcessAffinityMask = NULL; static inline VOID GetAffinityFuncs(VOID) { HMODULE h = GetModuleHandleA("kernel32.dll"); - pfnGetCurrentProcess = (p_GetCurrentProcess)GetProcAddress(h, "GetCurrentProcess"); - pfnGetProcessAffinityMask = (p_GetProcessAffinityMask)GetProcAddress(h, "GetProcessAffinityMask"); - pfnSetProcessAffinityMask = (p_SetProcessAffinityMask)GetProcAddress(h, "SetProcessAffinityMask"); + pfnGetCurrentProcess = (p_GetCurrentProcess)(LPVOID)GetProcAddress(h, "GetCurrentProcess"); + pfnGetProcessAffinityMask = (p_GetProcessAffinityMask)(LPVOID)GetProcAddress(h, "GetProcessAffinityMask"); + pfnSetProcessAffinityMask = (p_SetProcessAffinityMask)(LPVOID)GetProcAddress(h, "SetProcessAffinityMask"); } static void CPUAffinity_OnChange(void) diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 45f96e9d..ecdd0167 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -36,12 +36,6 @@ #include "../command.h" #include "../screen.h" -#ifdef HWRENDER -#include "win_dll.h" // loading the render DLL -#include "../hardware/hw_drv.h" // calling driver init & shutdown -#include "../hardware/hw_main.h" // calling HWR module init & shutdown -#endif - // ------- // Globals // ------- @@ -222,12 +216,7 @@ void I_StartupGraphics(void) if (graphics_started) return; -#ifdef HWRENDER - else if (M_CheckParm("-opengl")) - rendermode = render_opengl; - else -#endif - rendermode = render_soft; + rendermode = render_soft; if (dedicated) rendermode = render_none; @@ -245,10 +234,6 @@ void I_StartupGraphics(void) // ------------------ void I_ShutdownGraphics(void) { -#ifdef HWRENDER - const rendermode_t oldrendermode = rendermode; -#endif - // This is BAD because it makes the I_Error box screw up! // rendermode = render_none; @@ -273,15 +258,6 @@ void I_ShutdownGraphics(void) bmiMain = NULL; } -#ifdef HWRENDER - if (oldrendermode != render_soft) - { - HWR_Shutdown(); // free stuff from the hardware renderer - HWD.pfnShutdown(); // close 3d card display - Shutdown3DDriver(); // free the driver DLL - } -#endif - // free the last video mode screen buffers if (vid.buffer) { @@ -289,10 +265,7 @@ void I_ShutdownGraphics(void) vid.buffer = NULL; } -#ifdef HWRENDER - if (rendermode == render_soft) -#endif - CloseDirectDraw(); + CloseDirectDraw(); graphics_started = false; } @@ -380,11 +353,6 @@ void I_FinishUpdate(void) DIB_RGB_COLORS); } else -#ifdef HWRENDER - if (rendermode != render_soft) - HWD.pfnFinishUpdate(cv_vidwait.value); - else -#endif { // DIRECT DRAW // copy virtual screen to real screen @@ -486,9 +454,6 @@ void I_SetPalette(RGBA_t *palette) } } else -#ifdef HWRENDER - if (rendermode == render_soft) -#endif { PALETTEENTRY mainpal[256]; @@ -680,56 +645,14 @@ static VOID VID_Init(VOID) bDIBMode = TRUE; bAppFullScreen = FALSE; -#ifdef HWRENDER - // initialize the appropriate display device - if (rendermode != render_soft) + if (!bWinParm) { - const char *drvname = NULL; - - switch (rendermode) - { - case render_opengl: - drvname = "r_opengl.dll"; - break; - default: - I_Error("Unknown hardware render mode"); - } - - // load the DLL - if (drvname && Init3DDriver(drvname)) - { - int hwdversion = HWD.pfnGetRenderVersion(); - if (hwdversion != VERSION) - CONS_Alert(CONS_WARNING, M_GetText("This r_opengl version is not supported, use it at your own risk!\n")); - - // perform initialisations - HWD.pfnInit(I_Error); - // get available display modes for the device - HWD.pfnGetModeList(&pvidmodes, &numvidmodes); - } - else - { - switch (rendermode) - { - case render_opengl: - I_Error("Error initializing OpenGL"); - default: - break; - } - rendermode = render_soft; - } + if (!CreateDirectDrawInstance()) + bWinParm = TRUE; + else // get available display modes for the device + VID_GetExtraModes(); } - if (rendermode == render_soft) -#endif - if (!bWinParm) - { - if (!CreateDirectDrawInstance()) - bWinParm = TRUE; - else // get available display modes for the device - VID_GetExtraModes(); - } - // the game boots in 320x200 standard VGA, but // we need a highcolor mode to run the game in highcolor if (highcolor && !numvidmodes) @@ -927,14 +850,6 @@ INT32 VID_SetMode(INT32 modenum) // we switch to fullscreen bAppFullScreen = TRUE; bDIBMode = FALSE; -#ifdef HWRENDER - if (rendermode != render_soft) - { - // purge all patch graphics stored in software format - //Z_FreeTags (PU_PURGELEVEL, PU_PURGELEVEL+100); - HWR_Startup(); - } -#endif } I_RestartSysMouse(); diff --git a/src/win32ce/win_dll.c b/src/win32ce/win_dll.c index 8b88f84d..2bda7126 100644 --- a/src/win32ce/win_dll.c +++ b/src/win32ce/win_dll.c @@ -17,9 +17,6 @@ /// \brief load and initialise the 3D driver DLL #include "../doomdef.h" -#ifdef HWRENDER -#include "../hardware/hw_drv.h" // get the standard 3D Driver DLL exports prototypes -#endif #ifdef HW3SOUND #include "../hardware/hw3dsdrv.h" // get the 3D sound driver DLL export prototypes @@ -28,7 +25,7 @@ #include "win_dll.h" #include "win_main.h" // I_GetLastErrorMsgBox() -#if defined(HWRENDER) || defined(HW3SOUND) +#if defined(HW3SOUND) typedef struct loadfunc_s { LPCSTR fnName; LPVOID fnPointer; @@ -82,49 +79,6 @@ static inline 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[] = { - {"_Init@4", &hwdriver.pfnInit}, - {"_Shutdown@0", &hwdriver.pfnShutdown}, - {"_GetModeList@8", &hwdriver.pfnGetModeList}, - {"_SetPalette@8", &hwdriver.pfnSetPalette}, - {"_FinishUpdate@4", &hwdriver.pfnFinishUpdate}, - {"_Draw2DLine@12", &hwdriver.pfnDraw2DLine}, - {"_DrawPolygon@16", &hwdriver.pfnDrawPolygon}, - {"_SetBlend@4", &hwdriver.pfnSetBlend}, - {"_ClearBuffer@12", &hwdriver.pfnClearBuffer}, - {"_SetTexture@4", &hwdriver.pfnSetTexture}, - {"_ReadRect@24", &hwdriver.pfnReadRect}, - {"_GClipRect@20", &hwdriver.pfnGClipRect}, - {"_ClearMipMapCache@0",&hwdriver.pfnClearMipMapCache}, - {"_SetSpecialState@8", &hwdriver.pfnSetSpecialState}, - {"_DrawMD2@16", &hwdriver.pfnDrawMD2}, - {"_SetTransform@4", &hwdriver.pfnSetTransform}, - {"_GetTextureUsed@0", &hwdriver.pfnGetTextureUsed}, - {"_GetRenderVersion@0",&hwdriver.pfnGetRenderVersion}, - {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/win32ce/win_dll.h b/src/win32ce/win_dll.h index b4b25958..f69a8c21 100644 --- a/src/win32ce/win_dll.h +++ b/src/win32ce/win_dll.h @@ -20,11 +20,6 @@ #define RPC_NO_WINDOWS_H #include -#ifdef HWRENDER -BOOL Init3DDriver (LPCSTR dllName); -VOID Shutdown3DDriver (VOID); -#endif - #ifdef HW3SOUND BOOL Init3DSDriver(LPCSTR dllName); VOID Shutdown3DSDriver(VOID); diff --git a/src/win32ce/win_vid.c b/src/win32ce/win_vid.c index 244dfaf3..439103f3 100644 --- a/src/win32ce/win_vid.c +++ b/src/win32ce/win_vid.c @@ -34,12 +34,6 @@ #include "../command.h" #include "../screen.h" -#ifdef HWRENDER -#include "win_dll.h" // loading the render DLL -#include "../hardware/hw_drv.h" // calling driver init & shutdown -#include "../hardware/hw_main.h" // calling HWR module init & shutdown -#endif - // ------- // Globals // ------- @@ -110,13 +104,6 @@ void I_StartupGraphics(void) if (graphics_started) return; -#ifdef HWRENDER - if (M_CheckParm("-opengl")) - rendermode = render_opengl; - else - rendermode = render_soft; -#endif - if (dedicated) rendermode = render_none; else @@ -152,15 +139,6 @@ void I_ShutdownGraphics(void) bmiMain = NULL; } -#ifdef HWRENDER - if (rendermode != render_soft) - { - HWR_Shutdown(); // free stuff from the hardware renderer - HWD.pfnShutdown(); // close 3d card display - Shutdown3DDriver(); // free the driver DLL - } -#endif - // free the last video mode screen buffers if (vid.buffer) { @@ -168,10 +146,7 @@ void I_ShutdownGraphics(void) vid.buffer = NULL; } -#ifdef HWRENDER - if (rendermode == render_soft) -#endif - CloseDirectDraw(); + CloseDirectDraw(); graphics_started = false; } @@ -212,11 +187,6 @@ void I_FinishUpdate(void) DIB_RGB_COLORS); } else -#ifdef HWRENDER - if (rendermode != render_soft) - HWD.pfnFinishUpdate(cv_vidwait.value); - else -#endif { // DIRECT DRAW // copy virtual screen to real screen @@ -295,9 +265,6 @@ void I_SetPalette(RGBA_t *palette) } } else -#ifdef HWRENDER - if (rendermode == render_soft) -#endif { PALETTEENTRY mainpal[256]; @@ -458,56 +425,14 @@ static void VID_Init(void) bDIBMode = TRUE; bAppFullScreen = FALSE; -#ifdef HWRENDER - // initialize the appropriate display device - if (rendermode != render_soft) + if (!bWinParm) { - const char *drvname = NULL; - - switch (rendermode) - { - case render_opengl: - drvname = "r_opengl.dll"; - break; - default: - I_Error("Unknown hardware render mode"); - } - - // load the DLL - if (drvname && Init3DDriver(drvname)) - { - int hwdversion = HWD.pfnGetRenderVersion(); - if (hwdversion != VERSION) - CONS_Printf("WARNING: This r_opengl version is not supported, use it at your own risk.\n"); - - // perform initialisations - HWD.pfnInit(I_Error); - // get available display modes for the device - HWD.pfnGetModeList(&pvidmodes, &numvidmodes); - } - else - { - switch (rendermode) - { - case render_opengl: - I_Error("Error initializing OpenGL"); - default: - break; - } - rendermode = render_soft; - } + if (!CreateDirectDrawInstance()) + I_Error("Error initializing DirectDraw"); + // get available display modes for the device + VID_GetExtraModes(); } - if (rendermode == render_soft) -#endif - if (!bWinParm) - { - if (!CreateDirectDrawInstance()) - I_Error("Error initializing DirectDraw"); - // get available display modes for the device - VID_GetExtraModes(); - } - // the game boots in 320x200 standard VGA, but // we need a highcolor mode to run the game in highcolor if (highcolor && !numvidmodes) @@ -705,14 +630,6 @@ INT32 VID_SetMode(INT32 modenum) // we switch to fullscreen bAppFullScreen = TRUE; bDIBMode = FALSE; -#ifdef HWRENDER - if (rendermode != render_soft) - { - // purge all patch graphics stored in software format - //Z_FreeTags (PU_PURGELEVEL, PU_PURGELEVEL+100); - HWR_Startup(); - } -#endif } I_RestartSysMouse(); diff --git a/src/y_inter.c b/src/y_inter.c index 379694a1..29b681f7 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1251,6 +1251,10 @@ void Y_VoteTicker(void) if (paused || P_AutoPause() || !voteclient.loaded) return; +#ifdef HAVE_BLUA + LUAh_VoteThinker(); +#endif + votetic++; if (votetic == voteendtic) diff --git a/src/z_zone.c b/src/z_zone.c index a3e13422..dae7dff0 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -637,7 +637,6 @@ void Command_Memfree_f(void) 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 Texture used : %7d KB\n"), HWR_GetTextureUsed()>>10); } #endif