diff --git a/.gitignore b/.gitignore index 3090417dd..7023aaa80 100644 --- a/.gitignore +++ b/.gitignore @@ -13,11 +13,11 @@ Win32_LIB_ASM_Release *.dgb *.debug *.debug.txt -/bin/VC10/ -/objs/VC10/ *.user *.db *.opendb /.vs /debian /assets/debian +/make +/bin diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d2d4a7e6..6f901d3d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.13) # Enable CCache early set(SRB2_USE_CCACHE OFF CACHE BOOL "Use CCache") @@ -34,12 +34,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") ### Useful functions -# Prepend sources with current source directory -function(prepend_sources SOURCE_FILES) - foreach(SOURCE_FILE ${${SOURCE_FILES}}) - set(MODIFIED ${MODIFIED} ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}) - endforeach() - set(${SOURCE_FILES} ${MODIFIED} PARENT_SCOPE) +# Add sources from Sourcefile +function(target_sourcefile type) + file(STRINGS Sourcefile list + REGEX "[-0-9A-Za-z_]+\.${type}") + target_sources(SRB2SDL2 PRIVATE ${list}) endfunction() # Macro to add OSX framework diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..7ee12d837 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +ifdef SILENT +MAKEFLAGS+=--no-print-directory +endif + +all : + +% :: + @$(MAKE) -C src $(MAKECMDGOALS) diff --git a/README.md b/README.md index 8a5ca1a1f..49a3cc36d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Sonic Robo Blast 2 +[![latest release](https://badgen.net/github/release/STJr/SRB2/stable)](https://github.com/STJr/SRB2/releases/latest) [![Build status](https://ci.appveyor.com/api/projects/status/399d4hcw9yy7hg2y?svg=true)](https://ci.appveyor.com/project/STJr/srb2) [![Build status](https://travis-ci.org/STJr/SRB2.svg?branch=master)](https://travis-ci.org/STJr/SRB2) diff --git a/appveyor.yml b/appveyor.yml index 2acc2f712..d5f76c344 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.2.8.{branch}-{build} +version: 2.2.9.{branch}-{build} os: MinGW environment: @@ -99,16 +99,11 @@ build_script: - 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 +- cmd: 7z a %BUILD_ARCHIVE% bin -xr!.gitignore - appveyor PushArtifact %BUILD_ARCHIVE% #- cmd: copy %BUILD_ARCHIVE% %BUILDSARCHIVE% #- appveyor PushArtifact %BUILDSARCHIVE% diff --git a/bin/FreeBSD/Debug/.gitignore b/bin/FreeBSD/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/FreeBSD/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/FreeBSD/Release/.gitignore b/bin/FreeBSD/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/FreeBSD/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/Linux/Debug/.gitignore b/bin/Linux/Debug/.gitignore deleted file mode 100644 index 56dee6f95..000000000 --- a/bin/Linux/Debug/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/lsdlsrb2 diff --git a/bin/Linux/Release/.gitignore b/bin/Linux/Release/.gitignore deleted file mode 100644 index 5b5c54a54..000000000 --- a/bin/Linux/Release/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/lsdlsrb2 -/pnd -/*.mo diff --git a/bin/Linux64/Debug/.gitignore b/bin/Linux64/Debug/.gitignore deleted file mode 100644 index 56dee6f95..000000000 --- a/bin/Linux64/Debug/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/lsdlsrb2 diff --git a/bin/Linux64/Release/.gitignore b/bin/Linux64/Release/.gitignore deleted file mode 100644 index 56dee6f95..000000000 --- a/bin/Linux64/Release/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/lsdlsrb2 diff --git a/bin/Mingw/Debug/.gitignore b/bin/Mingw/Debug/.gitignore deleted file mode 100644 index 834f313e3..000000000 --- a/bin/Mingw/Debug/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.exe -*.mo -r_opengl.dll diff --git a/bin/Mingw/Release/.gitignore b/bin/Mingw/Release/.gitignore deleted file mode 100644 index 3458ff764..000000000 --- a/bin/Mingw/Release/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.exe -*.mo -r_opengl.dll -*.bat diff --git a/bin/Mingw64/Debug/.gitignore b/bin/Mingw64/Debug/.gitignore deleted file mode 100644 index e431dca5d..000000000 --- a/bin/Mingw64/Debug/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/srb2sdl.exe -/srb2win.exe -/r_opengl.dll diff --git a/bin/Mingw64/Release/.gitignore b/bin/Mingw64/Release/.gitignore deleted file mode 100644 index e431dca5d..000000000 --- a/bin/Mingw64/Release/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/srb2sdl.exe -/srb2win.exe -/r_opengl.dll diff --git a/bin/SDL/Debug/.gitignore b/bin/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/SDL/Release/.gitignore b/bin/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/VC/.gitignore b/bin/VC/.gitignore deleted file mode 100644 index e52f825b2..000000000 --- a/bin/VC/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/Release -/Debug diff --git a/bin/VC9/.gitignore b/bin/VC9/.gitignore deleted file mode 100644 index 205fe45de..000000000 --- a/bin/VC9/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/Win32 -/x64 diff --git a/bin/dummy/.gitignore b/bin/dummy/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/dummy/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/.gitignore b/dep/.gitignore deleted file mode 100644 index fb941664f..000000000 --- a/dep/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -#All folders -*.d diff --git a/dep/FreeBSD/SDL/Debug/.gitignore b/dep/FreeBSD/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/FreeBSD/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/FreeBSD/SDL/Release/.gitignore b/dep/FreeBSD/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/FreeBSD/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux/SDL/Debug/.gitignore b/dep/Linux/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux/SDL/Release/.gitignore b/dep/Linux/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux64/SDL/Debug/.gitignore b/dep/Linux64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux64/SDL/Release/.gitignore b/dep/Linux64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/MasterClient/.gitignore b/dep/MasterClient/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/MasterClient/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/MasterServer/.gitignore b/dep/MasterServer/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/MasterServer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/Debug/.gitignore b/dep/Mingw/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/Release/.gitignore b/dep/Mingw/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/SDL/Debug/.gitignore b/dep/Mingw/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/SDL/Release/.gitignore b/dep/Mingw/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/Debug/.gitignore b/dep/Mingw64/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/Release/.gitignore b/dep/Mingw64/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/SDL/Debug/.gitignore b/dep/Mingw64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/SDL/Release/.gitignore b/dep/Mingw64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/SDL/Release/.gitignore b/dep/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/VC/.gitignore b/dep/VC/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/VC/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/VC9/.gitignore b/dep/VC9/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/VC9/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/cygwin/Debug/.gitignore b/dep/cygwin/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/cygwin/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/cygwin/Release/.gitignore b/dep/cygwin/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/cygwin/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/dummy/.gitignore b/dep/dummy/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/dummy/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index a0d40cdf0..f457fe972 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -640,6 +640,39 @@ linedeftypes prefix = "(63)"; } + 96 + { + title = "Apply Tag to Tagged Sectors"; + prefix = "(96)"; + flags1024text = "[10] Offsets are target tags"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; + } + + 97 + { + title = "Apply Tag to Front Sector"; + prefix = "(97)"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; + } + + 98 + { + title = "Apply Tag to Back Sector"; + prefix = "(98)"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; + } + + 99 + { + title = "Apply Tag to Front and Back Sectors"; + prefix = "(99)"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; + } + 540 { title = "Floor Friction"; @@ -746,13 +779,13 @@ linedeftypes 20 { - title = "First Line"; + title = "PolyObject First Line"; prefix = "(20)"; } 22 { - title = "Parameters"; + title = "PolyObject Parameters"; prefix = "(22)"; flags8text = "[3] Set translucency by X offset"; flags32text = "[5] Render outer sides only"; @@ -765,19 +798,19 @@ linedeftypes 30 { - title = "Waving Flag"; + title = "PolyObject Waving Flag"; prefix = "(30)"; } 31 { - title = "Displacement by Front Sector"; + title = "Move PolyObject by Front Sector Displacement"; prefix = "(31)"; } 32 { - title = "Angular Displacement by Front Sector"; + title = "Rotate PolyObject by Front Sector Displacement"; prefix = "(32)"; flags64text = "[6] Don't turn players"; flags512text = "[9] Turn all objects"; @@ -2498,35 +2531,35 @@ linedeftypes 480 { - title = "Door Slide"; + title = "PolyObject Door Slide"; prefix = "(480)"; flags8text = "[3] Set delay by backside sector"; } 481 { - title = "Door Swing"; + title = "PolyObject Door Swing"; prefix = "(481)"; flags8text = "[3] Set delay by backside sector"; } 482 { - title = "Move"; + title = "Move PolyObject"; prefix = "(482)"; flags8text = "[3] Set delay by backside sector"; } 483 { - title = "Move, Override"; + title = "Move PolyObject, Override"; prefix = "(483)"; flags8text = "[3] Set delay by backside sector"; } 484 { - title = "Rotate Right"; + title = "Rotate PolyObject Right"; prefix = "(484)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2535,7 +2568,7 @@ linedeftypes 485 { - title = "Rotate Right, Override"; + title = "Rotate PolyObject Right, Override"; prefix = "(485)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2544,7 +2577,7 @@ linedeftypes 486 { - title = "Rotate Left"; + title = "Rotate PolyObject Left"; prefix = "(486)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2553,7 +2586,7 @@ linedeftypes 487 { - title = "Rotate Left, Override"; + title = "Rotate PolyObject Left, Override"; prefix = "(487)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Don't turn players"; @@ -2562,7 +2595,7 @@ linedeftypes 488 { - title = "Move by Waypoints"; + title = "Move PolyObject by Waypoints"; prefix = "(488)"; flags8text = "[3] Set delay by backside sector"; flags32text = "[5] Reverse order"; @@ -2573,7 +2606,7 @@ linedeftypes 489 { - title = "Turn Invisible, Intangible"; + title = "Turn PolyObject Invisible, Intangible"; prefix = "(489)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Only invisible"; @@ -2581,7 +2614,7 @@ linedeftypes 490 { - title = "Turn Visible, Tangible"; + title = "Turn PolyObject Visible, Tangible"; prefix = "(490)"; flags8text = "[3] Set delay by backside sector"; flags64text = "[6] Only visible"; @@ -2589,7 +2622,7 @@ linedeftypes 491 { - title = "Set Translucency"; + title = "Set PolyObject Translucency"; prefix = "(491)"; flags8text = "[3] Set delay by backside sector"; flags16text = "[4] Set raw alpha by Front X"; @@ -2598,7 +2631,7 @@ linedeftypes 492 { - title = "Fade Translucency"; + title = "Fade PolyObject Translucency"; prefix = "(492)"; flags8text = "[3] Set delay by backside sector"; flags16text = "[4] Set raw alpha by Front X"; @@ -3059,6 +3092,78 @@ linedeftypes slopeargs = 3; } + 723 + { + title = "Copy Backside Floor Slope from Line Tag"; + prefix = "(720)"; + slope = "copy"; + slopeargs = 4; + } + + 724 + { + title = "Copy Backside Ceiling Slope from Line Tag"; + prefix = "(721)"; + slope = "copy"; + slopeargs = 8; + } + + 725 + { + title = "Copy Backside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + slope = "copy"; + slopeargs = 12; + } + + 730 + { + title = "Copy Frontside Floor Slope to Backside"; + prefix = "(730)"; + slope = "copy"; + copyslopeargs = 1; + } + + 731 + { + title = "Copy Frontside Ceiling Slope to Backside"; + prefix = "(731)"; + slope = "copy"; + copyslopeargs = 4; + } + + 732 + { + title = "Copy Frontside Floor and Ceiling Slope to Backside"; + prefix = "(732)"; + slope = "copy"; + copyslopeargs = 5; + } + + 733 + { + title = "Copy Backside Floor Slope to Frontside"; + prefix = "(733)"; + slope = "copy"; + copyslopeargs = 2; + } + + 734 + { + title = "Copy Backside Ceiling Slope to Frontside"; + prefix = "(734)"; + slope = "copy"; + copyslopeargs = 8; + } + + 735 + { + title = "Copy Backside Floor and Ceiling Slope to Frontside"; + prefix = "(735)"; + slope = "copy"; + copyslopeargs = 10; + } + 799 { title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; @@ -3393,6 +3498,7 @@ thingtypes width = 8; height = 28; angletext = "Jump strength"; + fixedrotation = 1; } 103 { @@ -3431,6 +3537,7 @@ thingtypes width = 12; height = 64; angletext = "Firing delay"; + fixedrotation = 1; } 122 { @@ -3482,6 +3589,7 @@ thingtypes sprite = "ARCHA1"; width = 24; height = 32; + flags8text = "[8] Don't jump away"; } 118 { @@ -3547,9 +3655,10 @@ thingtypes { title = "Pterabyte Spawner"; sprite = "PTERA2A8"; - width = 16; - height = 16; - parametertext = "No. Pterabytes"; + width = 24; + height = 48; + parametertext = "Spawns +1"; + arrow = 0; } 136 { @@ -3771,6 +3880,7 @@ thingtypes height = 16; sprite = "internal:capsule"; angletext = "Tag"; + fixedrotation = 1; } 292 { @@ -3781,11 +3891,13 @@ thingtypes flags8text = "[8] Sea Egg shooting point"; sprite = "internal:eggmanway"; angletext = "No. (Sea Egg)"; + fixedrotation = 1; flagsvaluetext = "No. (Brak)"; parametertext = "Next"; } 293 { + arrow = 0; title = "Metal Sonic Gather Point"; sprite = "internal:metal"; width = 8; @@ -3793,6 +3905,7 @@ thingtypes } 294 { + arrow = 0; title = "Fang Waypoint"; flags8text = "[8] Center waypoint"; sprite = "internal:eggmanway"; @@ -3820,79 +3933,79 @@ thingtypes 301 { title = "Bounce Ring"; - sprite = "internal:RNGBA0"; + sprite = "RNGBA0"; } 302 { title = "Rail Ring"; - sprite = "internal:RNGRA0"; + sprite = "RNGRA0"; } 303 { title = "Infinity Ring"; - sprite = "internal:RNGIA0"; + sprite = "RNGIA0"; } 304 { title = "Automatic Ring"; - sprite = "internal:RNGAA0"; + sprite = "RNGAA0"; } 305 { title = "Explosion Ring"; - sprite = "internal:RNGEA0"; + sprite = "RNGEA0"; } 306 { title = "Scatter Ring"; - sprite = "internal:RNGSA0"; + sprite = "RNGSA0"; } 307 { title = "Grenade Ring"; - sprite = "internal:RNGGA0"; + sprite = "RNGGA0"; } 308 { title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; + sprite = "internal:TRNGA0r"; width = 16; } 309 { title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; + sprite = "internal:TRNGA0b"; width = 16; } 330 { title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; + sprite = "PIKBA0"; } 331 { title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; + sprite = "PIKRA0"; } 332 { title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; + sprite = "PIKAA0"; } 333 { title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; + sprite = "PIKEA0"; } 334 { title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; + sprite = "PIKSA0"; } 335 { title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; + sprite = "PIKGA0"; } } @@ -3986,6 +4099,7 @@ thingtypes flags8height = 24; flags8text = "[8] Float"; angletext = "Tag"; + fixedrotation = 1; } } @@ -4000,6 +4114,7 @@ thingtypes flags4text = "[4] Random (Strong)"; flags8text = "[8] Random (Weak)"; angletext = "Tag"; + fixedrotation = 1; 400 { @@ -4131,6 +4246,7 @@ thingtypes height = 44; flags1text = "[1] Run linedef executor on pop"; angletext = "Tag"; + fixedrotation = 1; 431 { @@ -4228,6 +4344,7 @@ thingtypes height = 128; flags4text = "[4] Respawn at center"; angletext = "Angle/Order"; + fixedrotation = 1; parametertext = "Order"; } 520 @@ -4259,7 +4376,7 @@ thingtypes flags1text = "[1] Start retracted"; flags4text = "[4] Retractable"; flags8text = "[8] Intangible"; - parametertext = "Initial delay"; + parametertext = "Start delay"; } 523 { @@ -4271,7 +4388,8 @@ thingtypes flags4text = "[4] Retractable"; flags8text = "[8] Intangible"; angletext = "Retraction interval"; - parametertext = "Initial delay"; + fixedrotation = 1; + parametertext = "Start delay"; } 1130 { @@ -4320,6 +4438,7 @@ thingtypes flags4text = "[4] Invisible"; flags8text = "[8] No distance check"; angletext = "Lift height"; + fixedrotation = 1; } 541 { @@ -4335,6 +4454,7 @@ thingtypes width = 32; height = 64; angletext = "Strength"; + fixedrotation = 1; } 543 { @@ -4344,6 +4464,7 @@ thingtypes height = 64; flags8text = "[8] Respawn"; angletext = "Color"; + fixedrotation = 1; } 550 { @@ -4617,6 +4738,9 @@ thingtypes title = "Slope Vertex"; sprite = "internal:vertexslope"; angletext = "Tag"; + fixedrotation = 1; + parametertext = "Absolute?"; + flagsvaluetext = "Absolute Z"; } 751 @@ -4638,6 +4762,7 @@ thingtypes title = "Zoom Tube Waypoint"; sprite = "internal:zoom"; angletext = "Order"; + fixedrotation = 1; } 754 @@ -4647,6 +4772,7 @@ thingtypes flags8text = "[8] Push using XYZ"; sprite = "GWLGA0"; angletext = "Radius"; + fixedrotation = 1; } 755 { @@ -4655,6 +4781,7 @@ thingtypes flags8text = "[8] Pull using XYZ"; sprite = "GWLRA0"; angletext = "Radius"; + fixedrotation = 1; } 756 { @@ -4663,6 +4790,7 @@ thingtypes width = 32; height = 16; angletext = "Tag"; + fixedrotation = 1; } 757 { @@ -4671,6 +4799,7 @@ thingtypes width = 8; height = 16; angletext = "Tag"; + fixedrotation = 1; } 758 { @@ -4681,21 +4810,24 @@ thingtypes { title = "PolyObject Anchor"; sprite = "internal:polyanchor"; - angletext = "ID"; + angletext = "Tag"; + fixedrotation = 1; } 761 { title = "PolyObject Spawn Point"; sprite = "internal:polycenter"; - angletext = "ID"; + angletext = "Tag"; + fixedrotation = 1; } 762 { title = "PolyObject Spawn Point (Crush)"; sprite = "internal:polycentercrush"; - angletext = "ID"; + angletext = "Tag"; + fixedrotation = 1; } 780 { @@ -4703,6 +4835,7 @@ thingtypes sprite = "internal:skyb"; flags4text = "[4] In-map centerpoint"; parametertext = "ID"; + fixedrotation = 1; } } @@ -4897,6 +5030,7 @@ thingtypes height = 16; hangs = 1; angletext = "Dripping interval"; + fixedrotation = 1; } 1003 { @@ -4953,7 +5087,7 @@ thingtypes 1011 { title = "Stalagmite (DSZ2)"; - sprite = "DSTGA0"; + sprite = "DSTGB0"; width = 8; height = 116; flags4text = "[4] Double size"; @@ -5038,6 +5172,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1105 { @@ -5048,6 +5184,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1106 { @@ -5058,6 +5196,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Red spring"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1107 { @@ -5067,6 +5207,8 @@ thingtypes height = 34; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1108 { @@ -5086,6 +5228,8 @@ thingtypes flags4text = "[4] No sounds"; flags8text = "[8] Double size"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1110 { @@ -5095,6 +5239,8 @@ thingtypes height = 34; flags4text = "[4] No sounds"; angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; } 1111 { @@ -5224,6 +5370,7 @@ thingtypes sprite = "EGR1A1"; width = 20; height = 72; + arrow = 1; } 1128 { @@ -5272,6 +5419,7 @@ thingtypes width = 8; height = 16; angletext = "Tag"; + fixedrotation = 1; } 1203 { @@ -5342,6 +5490,7 @@ thingtypes sprite = "WWSGAR"; width = 22; height = 64; + arrow = 1; } 1213 { @@ -5349,6 +5498,7 @@ thingtypes sprite = "WWS2AR"; width = 22; height = 64; + arrow = 1; } 1214 { @@ -5356,6 +5506,7 @@ thingtypes sprite = "WWS3ALAR"; width = 16; height = 192; + arrow = 1; } 1215 { @@ -5371,6 +5522,7 @@ thingtypes sprite = "BARRA1"; width = 24; height = 63; + arrow = 1; } 1217 { @@ -5392,6 +5544,7 @@ thingtypes sprite = "MCRTCLFR"; width = 22; height = 32; + arrow = 1; } 1220 { @@ -5399,6 +5552,7 @@ thingtypes sprite = "MCRTIR"; width = 32; height = 32; + arrow = 1; } 1221 { @@ -5406,6 +5560,7 @@ thingtypes sprite = "SALDARAL"; width = 96; height = 160; + arrow = 1; flags8text = "[8] Allow non-minecart players"; } 1222 @@ -5467,6 +5622,7 @@ thingtypes height = 40; flags8text = "[8] Waves vertically"; angletext = "On/Off time"; + fixedrotation = 1; parametertext = "Strength"; } 1301 @@ -5477,6 +5633,7 @@ thingtypes height = 40; flags8text = "[8] Shoot downwards"; angletext = "On/Off time"; + fixedrotation = 1; parametertext = "Strength"; } 1302 @@ -5500,6 +5657,7 @@ thingtypes width = 30; height = 32; angletext = "Initial delay"; + fixedrotation = 1; flags8text = "[8] Double size"; } 1305 @@ -5537,6 +5695,7 @@ thingtypes sprite = "WVINALAR"; width = 1; height = 288; + arrow = 1; } 1310 { @@ -5544,6 +5703,7 @@ thingtypes sprite = "WVINBLBR"; width = 1; height = 288; + arrow = 1; } } @@ -5901,6 +6061,7 @@ thingtypes width = 8; height = 4096; sprite = "UNKNA0"; + fixedrotation = 1; 1700 { @@ -5959,6 +6120,7 @@ thingtypes flags4text = "[4] Align player to top"; flags8text = "[8] Die upon time up"; angletext = "Time limit"; + fixedrotation = 1; parametertext = "Height"; } 1704 @@ -5971,6 +6133,7 @@ thingtypes unflippable = true; flagsvaluetext = "Pitch"; angletext = "Yaw"; + fixedrotation = 1; } 1705 { @@ -5983,6 +6146,7 @@ thingtypes centerHitbox = true; flagsvaluetext = "Height"; angletext = "Pitch/Yaw"; + fixedrotation = 1; } 1706 { @@ -6104,6 +6268,7 @@ thingtypes width = 8; height = 16; angletext = "Jump strength"; + fixedrotation = 1; } 1806 { @@ -6336,6 +6501,7 @@ thingtypes width = 18; height = 28; angletext = "Initial delay"; + fixedrotation = 1; } 2001 { @@ -6459,6 +6625,7 @@ thingtypes sprite = "XMS6A0"; width = 52; height = 106; + hangs = 1; } } @@ -6472,6 +6639,7 @@ thingtypes flags4text = "[4] No movement"; flags8text = "[8] Hop"; angletext = "Radius"; + fixedrotation = 1; 2200 { diff --git a/objs/.gitignore b/objs/.gitignore deleted file mode 100644 index 35ecd6def..000000000 --- a/objs/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -#All folders -SRB2.res -depend.dep -depend.ped -*.o -#VC9 folder only -/VC9/Win32 -/VC9/x64 diff --git a/objs/FreeBSD/SDL/Debug/.gitignore b/objs/FreeBSD/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/FreeBSD/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/FreeBSD/SDL/Release/.gitignore b/objs/FreeBSD/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/FreeBSD/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux/SDL/Debug/.gitignore b/objs/Linux/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux/SDL/Release/.gitignore b/objs/Linux/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux64/SDL/Debug/.gitignore b/objs/Linux64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux64/SDL/Release/.gitignore b/objs/Linux64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/MasterClient/.gitignore b/objs/MasterClient/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/MasterClient/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/MasterServer/.gitignore b/objs/MasterServer/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/MasterServer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/Debug/.gitignore b/objs/Mingw/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/Release/.gitignore b/objs/Mingw/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/SDL/Debug/.gitignore b/objs/Mingw/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/SDL/Release/.gitignore b/objs/Mingw/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/Debug/.gitignore b/objs/Mingw64/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/Release/.gitignore b/objs/Mingw64/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/SDL/Debug/.gitignore b/objs/Mingw64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/SDL/Release/.gitignore b/objs/Mingw64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/SDL/Release/.gitignore b/objs/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/VC/.gitignore b/objs/VC/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/VC/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/VC9/.gitignore b/objs/VC9/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/VC9/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/cygwin/Debug/.gitignore b/objs/cygwin/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/cygwin/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/cygwin/Release/.gitignore b/objs/cygwin/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/cygwin/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/dummy/.gitignore b/objs/dummy/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/dummy/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 87a0499b6..4c125c4b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,238 +1,14 @@ # SRB2 Core +add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32) + # Core sources -set(SRB2_CORE_SOURCES - am_map.c - b_bot.c - command.c - comptime.c - console.c - d_clisrv.c - d_main.c - d_net.c - d_netcmd.c - d_netfil.c - dehacked.c - deh_soc.c - deh_lua.c - deh_tables.c - f_finale.c - f_wipe.c - filesrch.c - g_demo.c - g_game.c - g_input.c - hu_stuff.c - i_tcp.c - info.c - lzf.c - m_aatree.c - m_anigif.c - m_argv.c - m_bbox.c - m_cheat.c - m_cond.c - m_fixed.c - m_menu.c - m_misc.c - m_perfstats.c - m_queue.c - m_random.c - md5.c - mserv.c - http-mserv.c - s_sound.c - screen.c - sounds.c - st_stuff.c - #string.c - tables.c - v_video.c - w_wad.c - y_inter.c - z_zone.c -) +target_sourcefile(c) +target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h) -set(SRB2_CORE_HEADERS - am_map.h - b_bot.h - byteptr.h - command.h - console.h - d_clisrv.h - d_event.h - d_main.h - d_net.h - d_netcmd.h - d_netfil.h - d_player.h - d_think.h - d_ticcmd.h - dehacked.h - deh_soc.h - deh_lua.h - deh_tables.h - doomdata.h - doomdef.h - doomstat.h - doomtype.h - endian.h - f_finale.h - fastcmp.h - filesrch.h - g_demo.h - g_game.h - g_input.h - g_state.h - hu_stuff.h - i_joy.h - i_net.h - i_sound.h - i_system.h - i_tcp.h - i_video.h - info.h - keys.h - lzf.h - m_aatree.h - m_anigif.h - m_argv.h - m_bbox.h - m_cheat.h - m_cond.h - m_dllist.h - m_fixed.h - m_menu.h - m_misc.h - m_perfstats.h - m_queue.h - m_random.h - m_swap.h - md5.h - mserv.h - p5prof.h - s_sound.h - screen.h - sounds.h - st_stuff.h - tables.h - v_video.h - w_wad.h - y_inter.h - z_zone.h - - config.h.in -) - -set(SRB2_CORE_RENDER_SOURCES - r_bsp.c - r_data.c - r_draw.c - r_main.c - r_plane.c - r_segs.c - r_skins.c - r_sky.c - r_splats.c - r_things.c - r_textures.c - r_patch.c - r_patchrotation.c - r_picformats.c - r_portal.c - - r_bsp.h - r_data.h - r_defs.h - r_draw.h - r_local.h - r_main.h - r_plane.h - r_segs.h - r_skins.h - r_sky.h - r_splats.h - r_state.h - r_things.h - r_textures.h - r_patch.h - r_patchrotation.h - r_picformats.h - r_portal.h -) - -set(SRB2_CORE_GAME_SOURCES - p_ceilng.c - p_enemy.c - p_floor.c - p_inter.c - p_lights.c - p_map.c - p_maputl.c - p_mobj.c - p_polyobj.c - p_saveg.c - p_setup.c - p_sight.c - p_slopes.c - p_spec.c - p_telept.c - p_tick.c - p_user.c - taglist.c - - p_local.h - p_maputl.h - p_mobj.h - p_polyobj.h - p_pspr.h - p_saveg.h - p_setup.h - p_slopes.h - p_spec.h - p_tick.h - taglist.h -) - -if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(SRB2_CORE_SOURCES ${SRB2_CORE_SOURCES} string.c) -endif() - -prepend_sources(SRB2_CORE_SOURCES) -prepend_sources(SRB2_CORE_HEADERS) -prepend_sources(SRB2_CORE_RENDER_SOURCES) -prepend_sources(SRB2_CORE_GAME_SOURCES) - -set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/config.h) -source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS}) -source_group("Renderer" FILES ${SRB2_CORE_RENDER_SOURCES}) -source_group("Game" FILES ${SRB2_CORE_GAME_SOURCES}) - - -set(SRB2_ASM_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/vid_copy.s -) - -set(SRB2_NASM_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/tmap_mmx.nas - ${CMAKE_CURRENT_SOURCE_DIR}/tmap.nas -) - -if(MSVC) - list(APPEND SRB2_NASM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tmap_vc.nas) -endif() - -set(SRB2_NASM_OBJECTS - ${CMAKE_CURRENT_BINARY_DIR}/tmap_mmx.obj - ${CMAKE_CURRENT_BINARY_DIR}/tmap.obj -) - -if(MSVC) - list(APPEND SRB2_NASM_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/tmap_vc.obj) -endif() - -source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES}) +set(SRB2_ASM_SOURCES vid_copy.s) +set(SRB2_NASM_SOURCES tmap_mmx.nas tmap.nas) ### Configuration set(SRB2_CONFIG_HAVE_PNG ON CACHE BOOL @@ -268,92 +44,7 @@ if(${CMAKE_SYSTEM} MATCHES "Windows") ###set on Windows only "Use SRB2's internal copies of required dependencies (SDL2, PNG, zlib, GME, OpenMPT).") endif() -set(SRB2_LUA_SOURCES - lua_baselib.c - lua_blockmaplib.c - lua_consolelib.c - lua_hooklib.c - lua_hudlib.c - lua_infolib.c - lua_maplib.c - lua_taglib.c - lua_mathlib.c - lua_mobjlib.c - lua_playerlib.c - lua_polyobjlib.c - lua_script.c - lua_skinlib.c - lua_thinkerlib.c -) -set(SRB2_LUA_HEADERS - lua_hook.h - lua_hud.h - lua_libs.h - lua_script.h -) - -prepend_sources(SRB2_LUA_SOURCES) -prepend_sources(SRB2_LUA_HEADERS) - -source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS}) - -set(SRB2_BLUA_SOURCES - blua/lapi.c - blua/lauxlib.c - blua/lbaselib.c - blua/lcode.c - blua/ldebug.c - blua/ldo.c - blua/ldump.c - blua/lfunc.c - blua/lgc.c - blua/linit.c - blua/liolib.c - blua/llex.c - blua/lmem.c - blua/lobject.c - blua/lopcodes.c - blua/lparser.c - blua/lstate.c - blua/lstring.c - blua/lstrlib.c - blua/ltable.c - blua/ltablib.c - blua/ltm.c - blua/lundump.c - blua/lvm.c - blua/lzio.c -) -set(SRB2_BLUA_HEADERS - blua/lapi.h - blua/lauxlib.h - blua/lcode.h - blua/ldebug.h - blua/ldo.h - blua/lfunc.h - blua/lgc.h - blua/llex.h - blua/llimits.h - blua/lmem.h - blua/lobject.h - blua/lopcodes.h - blua/lparser.h - blua/lstate.h - blua/lstring.h - blua/ltable.h - blua/ltm.h - blua/lua.h - blua/luaconf.h - blua/lualib.h - blua/lundump.h - blua/lvm.h - blua/lzio.h -) - -prepend_sources(SRB2_BLUA_SOURCES) -prepend_sources(SRB2_BLUA_HEADERS) - -source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS}) +add_subdirectory(blua) if(${SRB2_CONFIG_HAVE_GME}) if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) @@ -369,7 +60,7 @@ if(${SRB2_CONFIG_HAVE_GME}) endif() if(${GME_FOUND}) set(SRB2_HAVE_GME ON) - add_definitions(-DHAVE_LIBGME) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_LIBGME) else() message(WARNING "You have specified that GME is available but it was not found.") endif() @@ -389,7 +80,7 @@ if(${SRB2_CONFIG_HAVE_OPENMPT}) endif() if(${OPENMPT_FOUND}) set(SRB2_HAVE_OPENMPT ON) - add_definitions(-DHAVE_OPENMPT) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_OPENMPT) else() message(WARNING "You have specified that OpenMPT is available but it was not found.") endif() @@ -412,8 +103,7 @@ if(${SRB2_CONFIG_HAVE_MIXERX}) endif() if(${MIXERX_FOUND}) set(SRB2_HAVE_MIXERX ON) - set(SRB2_SDL2_SOUNDIMPL mixer_sound.c) - add_definitions(-DHAVE_MIXERX) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXERX) else() message(WARNING "You have specified that SDL Mixer X is available but it was not found.") endif() @@ -433,7 +123,7 @@ if(${SRB2_CONFIG_HAVE_ZLIB}) endif() if(${ZLIB_FOUND}) set(SRB2_HAVE_ZLIB ON) - add_definitions(-DHAVE_ZLIB) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_ZLIB) else() message(WARNING "You have specified that ZLIB is available but it was not found. SRB2 may not compile correctly.") endif() @@ -454,14 +144,9 @@ if(${SRB2_CONFIG_HAVE_PNG} AND ${SRB2_CONFIG_HAVE_ZLIB}) endif() if(${PNG_FOUND}) set(SRB2_HAVE_PNG ON) - add_definitions(-DHAVE_PNG) - add_definitions(-D_LARGEFILE64_SOURCE) - set(SRB2_PNG_SOURCES apng.c) - set(SRB2_PNG_HEADERS apng.h) - prepend_sources(SRB2_PNG_SOURCES) - prepend_sources(SRB2_PNG_HEADERS) - source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS} - ${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS}) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_PNG) + target_compile_definitions(SRB2SDL2 PRIVATE -D_LARGEFILE64_SOURCE) + target_sources(SRB2SDL2 PRIVATE apng.c) else() message(WARNING "You have specified that PNG is available but it was not found. SRB2 may not compile correctly.") endif() @@ -482,7 +167,7 @@ if(${SRB2_CONFIG_HAVE_CURL}) endif() if(${CURL_FOUND}) set(SRB2_HAVE_CURL ON) - add_definitions(-DHAVE_CURL) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_CURL) else() message(WARNING "You have specified that CURL is available but it was not found. SRB2 may not compile correctly.") endif() @@ -490,59 +175,19 @@ endif() if(${SRB2_CONFIG_HAVE_THREADS}) set(SRB2_HAVE_THREADS ON) - set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/i_threads.h) - add_definitions(-DHAVE_THREADS) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_THREADS) endif() if(${SRB2_CONFIG_HWRENDER}) - add_definitions(-DHWRENDER) - set(SRB2_HWRENDER_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c - ) - - set (SRB2_HWRENDER_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h - ${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_glob.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h - ) - - set(SRB2_R_OPENGL_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.c - ) - - set(SRB2_R_OPENGL_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.h - ) - + target_compile_definitions(SRB2SDL2 PRIVATE -DHWRENDER) + add_subdirectory(hardware) endif() if(${SRB2_CONFIG_HWRENDER} AND ${SRB2_CONFIG_STATIC_OPENGL}) find_package(OpenGL) if(${OPENGL_FOUND}) - add_definitions(-DHWRENDER) - add_definitions(-DSTATIC_OPENGL) + target_compile_definitions(SRB2SDL2 PRIVATE -DHWRENDER) + target_compile_definitions(SRB2SDL2 PRIVATE -DSTATIC_OPENGL) else() message(WARNING "You have specified static opengl but opengl was not found. Not setting HWRENDER.") endif() @@ -563,12 +208,16 @@ if(${SRB2_CONFIG_USEASM}) set(CMAKE_ASM_NASM_FLAGS "${SRB2_ASM_FLAGS}" CACHE STRING "Flags used by the assembler during all build types.") enable_language(ASM_NASM) endif() + set(SRB2_USEASM ON) - add_definitions(-DUSEASM) + target_compile_definitions(SRB2SDL2 PRIVATE -DUSEASM) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse") + + target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES} + ${SRB2_NASM_SOURCES}) else() set(SRB2_USEASM OFF) - add_definitions(-DNONX86 -DNORUSEASM) + target_compile_definitions(SRB2SDL2 PRIVATE -DNONX86 -DNORUSEASM) endif() # Targets @@ -604,7 +253,9 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -Wno-absolute-value) endif() -add_definitions(-DCMAKECONFIG) +set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -Wno-trigraphs) + +target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG) #add_library(SRB2Core STATIC # ${SRB2_CORE_SOURCES} diff --git a/src/Makefile b/src/Makefile index 9518942b2..90776b812 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,824 +1,414 @@ - -# GNU Make makefile for SRB2 -############################################################################# -# Copyright (C) 1998-2000 by DooM Legacy Team. -# Copyright (C) 2003-2021 by Sonic Team Junior. +# GNU Makefile for SRB2 +# the poly3 Makefile adapted over and over... +# +# Copyright 1998-2000 DooM Legacy Team. +# Copyright 2020-2021 James R. +# Copyright 2003-2021 Sonic Team Junior. # # This program is free software distributed under the # terms of the GNU General Public License, version 2. # See the 'LICENSE' file for more details. # -# -DLINUX -> use for the GNU/Linux specific -# -D_WINDOWS -> use for the Win32/DirectX specific -# -DHAVE_SDL -> use for the SDL interface +# Special targets: # -# Sets: -# Compile the SDL/Mingw version with 'make MINGW=1' -# Compile the SDL/Linux version with 'make LINUX=1' -# Compile the SDL/Solaris version with 'make SOLARIS=1' -# Compile the SDL/FreeBSD version with 'gmake FREEBSD=1' -# Compile the SDL/Cygwin version with 'make CYGWIN32=1' -# Compile the SDL/other version try with 'make SDL=1' +# clean - remove executables and objects for this build +# cleandep - remove dependency files for this build +# distclean - remove entire executable, object and +# dependency file directory structure. +# dump - disassemble executable +# info - print settings # -# 'Targets': -# clean -# Remove all object files -# cleandep -# Remove dependency files -# distclean -# Remove autogenerated files -# dll -# compile primary HW render DLL/SO -# all_dll -# compile all HW render and 3D sound DLLs for the set -# opengl_dll -# Pure Mingw only, compile OpenGL HW render DLL -# ds3d_dll -# Pure Mingw only, compile DirectX DirectSound HW sound DLL -# fmod_dll -# Pure Mingw only, compile FMOD HW sound DLL -# openal_dll -# Pure Mingw only, compile OpenAL HW sound DLL -# fmod_so -# Non-Mingw, compile FMOD HW sound SO -# openal_so -# Non-Mingw, compile OpenAL HW sound SO +# This Makefile can automatically detect the host system +# as well as the compiler version. If system or compiler +# version cannot be detected, you may need to set a flag +# manually. # +# On Windows machines, 32-bit Windows is always targetted. # -# Addon: -# To Cross-Compile, CC=gcc-version make * PREFIX= -# Compile with GCC 2.97 version, add 'GCC29=1' -# Compile with GCC 4.0x version, add 'GCC40=1' -# Compile with GCC 4.1x version, add 'GCC41=1' -# Compile with GCC 4.2x version, add 'GCC42=1' -# Compile with GCC 4.3x version, add 'GCC43=1' -# Compile with GCC 4.4x version, add 'GCC44=1' -# Compile with GCC 4.5x version, add 'GCC45=1' -# Compile with GCC 4.6x version, add 'GCC46=1' -# Compile a profile version, add 'PROFILEMODE=1' -# Compile a debug version, add 'DEBUGMODE=1' -# Compile with less warnings, add 'RELAXWARNINGS=1' -# Generate compiler errors for most compiler warnings, add 'ERRORMODE=1' -# Compile without NASM's tmap.nas, add 'NOASM=1' -# Compile without 3D hardware support, add 'NOHW=1' -# Compile with GDBstubs, add 'RDB=1' -# Compile without PNG, add 'NOPNG=1' -# Compile without zlib, add 'NOZLIB=1' +# Platform/system flags: # -# Addon for SDL: -# To Cross-Compile, add 'SDL_CONFIG=/usr/*/bin/sdl-config' -# Compile without SDL_Mixer, add 'NOMIXER=1' -# Compile without SDL_Mixer_X, add 'NOMIXERX=1' (Win32 only) -# Compile without GME, add 'NOGME=1' -# Compile without BSD API, add 'NONET=1' -# Compile without IPX/SPX, add 'NOIPX=1' -# Compile Mingw/SDL with S_DS3S, add 'DS3D=1' -# Compile without libopenmpt, add 'NOOPENMPT=1' -# Compile with S_FMOD3D, add 'FMOD=1' (WIP) -# Compile with S_OPENAL, add 'OPENAL=1' (WIP) -# To link with the whole SDL_Image lib to load Icons, add 'SDL_IMAGE=1' but it isn't not realy needed -# To link with SDLMain to hide console or make on a console-less binary, add 'SDLMAIN=1' +# LINUX=1, LINUX64=1 +# MINGW=1, MINGW64=1 - Windows (MinGW toolchain) +# UNIX=1 - Generic Unix like system +# FREEBSD=1 +# SDL=1 - Use SDL backend. SDL is the only backend though +# and thus, always enabled. # -############################################################################# +# A list of supported GCC versions can be found in +# Makefile.d/detect.mk -- search 'gcc_versions'. +# +# Feature flags: +# +# Safe to use online +# ------------------ +# NO_IPV6=1 - Disable IPv6 address support. +# NOHW=1 - Disable OpenGL renderer. +# ZDEBUG=1 - Enable more detailed memory debugging +# HAVE_MINIUPNPC=1 - Enable automated port forwarding. +# Already enabled by default for 32-bit +# Windows. +# NOASM=1 - Disable hand optimized assembly code for the +# Software renderer. +# NOPNG=1 - Disable PNG graphics support. (TODO: double +# check netplay compatible.) +# NOCURL=1 - Disable libcurl--HTTP capability. +# NOGME=1 - Disable game music emu, retro VGM support. +# NOOPENMPT=1 - Disable module (tracker) music support. +# NOMIXER=1 - Disable SDL Mixer (audio playback). +# NOMIXERX=1 - Forgo SDL Mixer X--revert to standard SDL +# Mixer. Mixer X is the default for Windows +# builds. +# HAVE_MIXERX=1 - Enable SDL Mixer X. Outside of Windows +# builds, SDL Mixer X is not the default. +# NOTHREADS=1 - Disable multithreading. +# +# Netplay incompatible +# -------------------- +# NONET=1 - Disable online capability. +# NOMD5=1 - Disable MD5 checksum (validation tool). +# NOPOSTPROCESSING=1 - ? +# MOBJCONSISTANCY=1 - ?? +# PACKETDROP=1 - ?? +# DEBUGMODE=1 - Enable various debugging capabilities. +# Also disables optimizations. +# NOZLIB=1 - Disable some compression capability. Implies +# NOPNG=1. +# +# Development flags: +# +# VALGRIND=1 - Enable Valgrind memory debugging support. +# PROFILEMODE=1 - Enable performance profiling (gprof). +# +# General flags for building: +# +# STATIC=1 - Use static linking. +# DISTCC=1 +# CCACHE=1 +# UPX= - UPX command to use for compressing final +# executable. +# WINDOWSHELL=1 - Use Windows commands. +# PREFIX= - Prefix to many commands, for cross compiling. +# YASM=1 - Use Yasm instead of NASM assembler. +# STABS=1 - ? +# ECHO=1 - Print out each command in the build process. +# NOECHOFILENAMES=1 - Don't print out each that is being +# worked on. +# SILENT=1 - Print absolutely nothing except errors. +# RELAXWARNINGS=1 - Use less compiler warnings/errors. +# ERRORMODE=1 - Treat most compiler warnings as errors. +# NOCASTALIGNWARN=1 - ? +# NOLDWARNING=1 - ? +# NOSDLMAIN=1 - ? +# SDLMAIN=1 - ? +# +# Library configuration flags: +# Everything here is an override. +# +# PNG_PKGCONFIG= - libpng-config command. +# PNG_CFLAGS=, PNG_LDFLAGS= +# +# CURLCONFIG= - curl-config command. +# CURL_CFLAGS=, CURL_LDFLAGS= +# +# VALGRIND_PKGCONFIG= - pkg-config package name. +# VALGRIND_CFLAGS=, VALGRIND_LDFLAGS= +# +# LIBGME_PKGCONFIG=, LIBGME_CFLAGS=, LIBGME_LDFLAGS= -,=, +# LIBOPENMPT_PKGCONFIG= +# LIBOPENMPT_CFLAGS=, LIBOPENMPT_LDFLAGS= +# +# ZLIB_PKGCONFIG=, ZLIB_CFLAGS=, ZLIB_LDFLAGS= +# +# SDL_PKGCONFIG= +# SDL_CONFIG= - sdl-config command. +# SDL_CFLAGS=, SDL_LDFLAGS= -ifeq (,$(filter-out cleandep clean distclean,$(or $(MAKECMDGOALS),all))) -CLEANONLY=1 -else ifndef SILENT -echo=@echo "$(1)" -ifndef MAKE_RESTARTS -print=$(info $(1)) -endif +clean_targets=cleandep clean distclean info + +.PHONY : $(clean_targets) all + +goals:=$(or $(MAKECMDGOALS),all) +cleanonly:=$(filter $(clean_targets),$(goals)) +destructive:=$(filter-out info,$(cleanonly)) + +ifndef cleanonly +include Makefile.d/old.mk endif -ALL_SYSTEMS=\ - PANDORA\ - LINUX64\ - MINGW64\ - HAIKU\ - DUMMY\ - DJGPPDOS\ - MINGW\ - UNIX\ - LINUX\ - SOLARIS\ - FREEBSD\ - MACOSX\ - SDL\ +include Makefile.d/util.mk -# check for user specified system -ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES))) -ifeq ($(OS),Windows_NT) # all windows are Windows_NT... - - $(call print,Detected a Windows system$(,) compiling for 32-bit MinGW SDL2...) - - # go for a 32-bit sdl mingw exe by default - MINGW=1 - WINDOWSHELL=1 - -else # if you on the *nix - - system:=$(shell uname -s) - - ifeq ($(system),Linux) - new_system=LINUX - else - - $(error \ - Could not automatically detect your system,\ - try specifying a system manually) - - endif - - ifeq ($(shell getconf LONG_BIT),64) - system+=64-bit - new_system:=$(new_system)64 - endif - - $(call print,Detected $(system) ($(new_system))...) - $(new_system)=1 - -endif -endif - - -# SRB2 data files -D_DIR?=../bin/Resources -D_FILES=$(D_DIR)/srb2.pk3 \ - $(D_DIR)/player.dta \ - $(D_DIR)/zones.pk3 \ - $(D_DIR)/music.dta \ - -PKG_CONFIG?=pkg-config - -ifdef PANDORA -LINUX=1 -endif - -ifdef LINUX64 -LINUX=1 -NONX86=1 -# LINUX64 does not imply X86_64=1; could mean ARM64 or Itanium -endif - -ifdef MINGW64 -MINGW=1 -NONX86=1 -NOASM=1 -# MINGW64 should not necessarily imply X86_64=1, but we make that assumption elsewhere -# Once that changes, remove this -X86_64=1 -endif #ifdef MINGW64 - -ifdef HAIKU -SDL=1 -endif - -include Makefile.cfg - -ifdef DUMMY -NOPNG=1 -NOZLIB=1 -NONET=1 -NOHW=1 -NOASM=1 -NOIPX=1 -EXENAME?=srb2dummy -OBJS=$(OBJDIR)/i_video.o -LIBS=-lm -endif - -ifdef HAIKU -NOIPX=1 -NOASM=1 -ifndef NONET -LIBS=-lnetwork -endif -CFLAGS+=-DUNIXCOMMON -PNG_CFLAGS?= -PNG_LDFLAGS?=-lpng -endif - -ifdef PANDORA -NONX86=1 -NOHW=1 -endif - -ifndef NOOPENMPT -HAVE_OPENMPT=1 -endif - -ifdef MINGW -include win32/Makefile.cfg -endif #ifdef MINGW - -ifdef UNIX -UNIXCOMMON=1 -endif - -ifdef LINUX -UNIXCOMMON=1 -ifndef NOGME -HAVE_LIBGME=1 -endif -endif - -ifdef SOLARIS -UNIXCOMMON=1 -endif - -ifdef FREEBSD -UNIXCOMMON=1 -endif - -ifdef MACOSX -UNIXCOMMON=1 -endif - -ifdef SDL - include sdl/Makefile.cfg -endif #ifdef SDL - -ifdef DISTCC - CC:=distcc $(CC) -endif - -ifdef CCACHE - CC:=ccache $(CC) -endif - -MSGFMT?=msgfmt - -ifdef WINDOWSHELL - COMPTIME=-..\comptime.bat -else - COMPTIME=-../comptime.sh -endif - -ifndef ECHO - NASM:=@$(NASM) - REMOVE:=@$(REMOVE) - CC:=@$(CC) - CXX:=@$(CXX) - OBJCOPY:=@$(OBJCOPY) - OBJDUMP:=@$(OBJDUMP) - STRIP:=@$(STRIP) - WINDRES:=@$(WINDRES) - MKDIR:=@$(MKDIR) - GZIP:=@$(GZIP) - MSGFMT:=@$(MSGFMT) - UPX:=@$(UPX) - UPX_OPTS+=-q - COMPTIME:=@$(COMPTIME) -endif - -ifdef NONET - OPTS+=-DNONET - NOCURL=1 -else -ifdef NO_IPV6 - OPTS+=-DNO_IPV6 -endif -endif - -ifdef NOHW - OPTS+=-DNOHW -else - OPTS+=-DHWRENDER - OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ - $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o \ - $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o -endif - -OPTS += -DCOMPVERSION - -ifndef NONX86 -ifndef GCC29 - ARCHOPTS?=-msse3 -mfpmath=sse -else - ARCHOPTS?=-mpentium -endif -else -ifdef X86_64 - ARCHOPTS?=-march=nocona -endif -endif - -ifndef NOASM -ifndef NONX86 - OBJS+=$(OBJDIR)/tmap.o $(OBJDIR)/tmap_mmx.o - OPTS+=-DUSEASM -endif -endif - -ifndef NOPNG -OPTS+=-DHAVE_PNG - -ifdef PNG_PKGCONFIG -PNG_CFLAGS?=$(shell $(PKG_CONFIG) $(PNG_PKGCONFIG) --cflags) -PNG_LDFLAGS?=$(shell $(PKG_CONFIG) $(PNG_PKGCONFIG) --libs) -else ifdef PREFIX -PNG_CONFIG?=$(PREFIX)-libpng-config +CC:=$(PREFIX)-gcc +endif + +OBJDUMP_OPTS?=--wide --source --line-numbers + +OBJCOPY:=$(call Prefix,objcopy) +OBJDUMP:=$(call Prefix,objdump) +WINDRES:=$(call Prefix,windres) + +ifdef YASM +NASM?=yasm else -PNG_CONFIG?=libpng-config +NASM?=nasm endif -ifdef PNG_STATIC -PNG_CFLAGS?=$(shell $(PNG_CONFIG) --static --cflags) -PNG_LDFLAGS?=$(shell $(PNG_CONFIG) --static --ldflags) -else -PNG_CFLAGS?=$(shell $(PNG_CONFIG) --cflags) -PNG_LDFLAGS?=$(shell $(PNG_CONFIG) --ldflags) -endif -endif - -ifdef LINUX -PNG_CFLAGS+=-D_LARGEFILE64_SOURCE -endif - -LIBS+=$(PNG_LDFLAGS) -CFLAGS+=$(PNG_CFLAGS) - -OBJS+=$(OBJDIR)/apng.o -endif - -ifdef HAVE_LIBGME -OPTS+=-DHAVE_LIBGME - -LIBGME_PKGCONFIG?=libgme -LIBGME_CFLAGS?=$(shell $(PKG_CONFIG) $(LIBGME_PKGCONFIG) --cflags) -LIBGME_LDFLAGS?=$(shell $(PKG_CONFIG) $(LIBGME_PKGCONFIG) --libs) - -LIBS+=$(LIBGME_LDFLAGS) -CFLAGS+=$(LIBGME_CFLAGS) -endif - -ifdef HAVE_OPENMPT -OPTS+=-DHAVE_OPENMPT - -LIBOPENMPT_PKGCONFIG?=libopenmpt -LIBOPENMPT_CFLAGS?=$(shell $(PKG_CONFIG) $(LIBOPENMPT_PKGCONFIG) --cflags) -LIBOPENMPT_LDFLAGS?=$(shell $(PKG_CONFIG) $(LIBOPENMPT_PKGCONFIG) --libs) - -LIBS+=$(LIBOPENMPT_LDFLAGS) -CFLAGS+=$(LIBOPENMPT_CFLAGS) -endif - -ifndef NOZLIB -OPTS+=-DHAVE_ZLIB -ZLIB_PKGCONFIG?=zlib -ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags) -ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs) - -LIBS+=$(ZLIB_LDFLAGS) -CFLAGS+=$(ZLIB_CFLAGS) -else -NOPNG=1 -endif - -ifndef NOCURL -OPTS+=-DHAVE_CURL -CURLCONFIG?=curl-config -CURL_CFLAGS?=$(shell $(CURLCONFIG) --cflags) -CURL_LDFLAGS?=$(shell $(CURLCONFIG) --libs) - -LIBS+=$(CURL_LDFLAGS) -CFLAGS+=$(CURL_CFLAGS) -endif - -ifdef STATIC -LIBS:=-static $(LIBS) -endif - -ifdef HAVE_MINIUPNPC -ifdef NONET -HAVE_MINIUPNPC='' -else -LIBS+=-lminiupnpc -ifdef MINGW -LIBS+=-lws2_32 -liphlpapi -endif -CFLAGS+=-DHAVE_MINIUPNPC -endif -endif - -include blua/Makefile.cfg - -ifdef NOMD5 - OPTS+=-DNOMD5 -else - OBJS:=$(OBJDIR)/md5.o $(OBJS) -endif - -ifdef NOPOSTPROCESSING - OPTS+=-DNOPOSTPROCESSING -endif - - OPTS:=-fno-exceptions $(OPTS) - -ifdef MOBJCONSISTANCY - OPTS+=-DMOBJCONSISTANCY -endif - -ifdef PACKETDROP - OPTS+=-DPACKETDROP -endif - -ifdef DEBUGMODE - - # build with debugging information - WINDRESFLAGS = -D_DEBUG -ifdef GCC48 - CFLAGS+=-Og -else - CFLAGS+=-O0 -endif - CFLAGS+= -Wall -DPARANOIA -DRANGECHECK -DPACKETDROP -else - - - # build a normal optimised version - WINDRESFLAGS = -DNDEBUG - CFLAGS+=-O3 -endif - CFLAGS+=-g $(OPTS) $(ARCHOPTS) $(WINDRESFLAGS) - ifdef YASM ifdef STABS - NASMOPTS?= -g stabs +NASMOPTS?=-g stabs else - NASMOPTS?= -g dwarf2 +NASMOPTS?=-g dwarf2 endif else - NASMOPTS?= -g +NASMOPTS?=-g endif -ifdef PROFILEMODE - # build with profiling information - CFLAGS+=-pg - LDFLAGS+=-pg +GZIP?=gzip +GZIP_OPTS?=-9 -f -n +ifdef WINDOWSHELL +GZIP_OPTS+=--rsyncable endif -ifdef ZDEBUG - CPPFLAGS+=-DZDEBUG +UPX_OPTS?=--best --preserve-build-id +ifndef ECHO +UPX_OPTS+=-qq endif -OPTS+=$(CPPFLAGS) +include Makefile.d/detect.mk -# default EXENAME if all else fails +# make would try to remove the implicitly made directories +.PRECIOUS : %/ comptime.c + +sources:= +makedir:=../make + +# -DCOMPVERSION: flag to use comptime.h +opts:=-DCOMPVERSION -g +libs:= + +nasm_format:= + +# This is a list of variables names, of which if defined, +# also defines the name as a macro to the compiler. +passthru_opts:= + +include Makefile.d/platform.mk +include Makefile.d/features.mk +include Makefile.d/versions.mk + +ifdef DEBUGMODE +makedir:=$(makedir)/debug +endif + +depdir:=$(makedir)/deps +objdir:=$(makedir)/objs + +# very sophisticated dependency +sources+=\ + $(call List,Sourcefile)\ + $(call List,blua/Sourcefile)\ + +depends:=$(basename $(filter %.c %.s,$(sources))) +objects:=$(basename $(filter %.c %.s %.nas,$(sources))) + +depends:=$(depends:%=$(depdir)/%.d) + +# comptime.o added directly to objects instead of thru +# sources because comptime.c includes comptime.h, but +# comptime.h may not exist yet. It's a headache so this is +# easier. +objects:=$(objects:=.o) comptime.o + +# windows resource file +rc_file:=$(basename $(filter %.rc,$(sources))) +ifdef rc_file +objects+=$(rc_file:=.res) +endif + +objects:=$(addprefix $(objdir)/,$(objects)) + +ifdef DEBUGMODE +bin:=../bin/debug +else +bin:=../bin +endif + +# default EXENAME (usually set by platform) EXENAME?=srb2 DBGNAME?=$(EXENAME).debug -# $(OBJDIR)/dstrings.o \ +exe:=$(bin)/$(EXENAME) +dbg:=$(bin)/$(DBGNAME) -# not too sophisticated dependency -OBJS:=$(i_main_o) \ - $(OBJDIR)/string.o \ - $(OBJDIR)/d_main.o \ - $(OBJDIR)/d_clisrv.o \ - $(OBJDIR)/d_net.o \ - $(OBJDIR)/d_netfil.o \ - $(OBJDIR)/d_netcmd.o \ - $(OBJDIR)/dehacked.o \ - $(OBJDIR)/deh_soc.o \ - $(OBJDIR)/deh_lua.o \ - $(OBJDIR)/deh_tables.o \ - $(OBJDIR)/z_zone.o \ - $(OBJDIR)/f_finale.o \ - $(OBJDIR)/f_wipe.o \ - $(OBJDIR)/g_demo.o \ - $(OBJDIR)/g_game.o \ - $(OBJDIR)/g_input.o \ - $(OBJDIR)/am_map.o \ - $(OBJDIR)/command.o \ - $(OBJDIR)/console.o \ - $(OBJDIR)/hu_stuff.o \ - $(OBJDIR)/y_inter.o \ - $(OBJDIR)/st_stuff.o \ - $(OBJDIR)/m_aatree.o \ - $(OBJDIR)/m_anigif.o \ - $(OBJDIR)/m_argv.o \ - $(OBJDIR)/m_bbox.o \ - $(OBJDIR)/m_cheat.o \ - $(OBJDIR)/m_cond.o \ - $(OBJDIR)/m_fixed.o \ - $(OBJDIR)/m_menu.o \ - $(OBJDIR)/m_misc.o \ - $(OBJDIR)/m_perfstats.o \ - $(OBJDIR)/m_random.o \ - $(OBJDIR)/m_queue.o \ - $(OBJDIR)/info.o \ - $(OBJDIR)/p_ceilng.o \ - $(OBJDIR)/p_enemy.o \ - $(OBJDIR)/p_floor.o \ - $(OBJDIR)/p_inter.o \ - $(OBJDIR)/p_lights.o \ - $(OBJDIR)/p_map.o \ - $(OBJDIR)/p_maputl.o \ - $(OBJDIR)/p_mobj.o \ - $(OBJDIR)/p_polyobj.o\ - $(OBJDIR)/p_saveg.o \ - $(OBJDIR)/p_setup.o \ - $(OBJDIR)/p_sight.o \ - $(OBJDIR)/p_spec.o \ - $(OBJDIR)/p_telept.o \ - $(OBJDIR)/p_tick.o \ - $(OBJDIR)/p_user.o \ - $(OBJDIR)/p_slopes.o \ - $(OBJDIR)/tables.o \ - $(OBJDIR)/r_bsp.o \ - $(OBJDIR)/r_data.o \ - $(OBJDIR)/r_draw.o \ - $(OBJDIR)/r_main.o \ - $(OBJDIR)/r_plane.o \ - $(OBJDIR)/r_segs.o \ - $(OBJDIR)/r_skins.o \ - $(OBJDIR)/r_sky.o \ - $(OBJDIR)/r_splats.o \ - $(OBJDIR)/r_things.o \ - $(OBJDIR)/r_textures.o \ - $(OBJDIR)/r_patch.o \ - $(OBJDIR)/r_patchrotation.o \ - $(OBJDIR)/r_picformats.o \ - $(OBJDIR)/r_portal.o \ - $(OBJDIR)/screen.o \ - $(OBJDIR)/taglist.o \ - $(OBJDIR)/v_video.o \ - $(OBJDIR)/s_sound.o \ - $(OBJDIR)/sounds.o \ - $(OBJDIR)/w_wad.o \ - $(OBJDIR)/filesrch.o \ - $(OBJDIR)/mserv.o \ - $(OBJDIR)/http-mserv.o\ - $(OBJDIR)/i_tcp.o \ - $(OBJDIR)/lzf.o \ - $(OBJDIR)/vid_copy.o \ - $(OBJDIR)/b_bot.o \ - $(i_net_o) \ - $(i_system_o) \ - $(i_sound_o) \ - $(OBJS) +build_done==== Build is done, look for \ + $( $@ + $(.)$(GZIP) $(GZIP_OPTS) $@ -ifdef SDL -all: $(BIN)/$(EXENAME) -endif - -ifdef DUMMY -all: $(BIN)/$(EXENAME) -endif - -cleandep: - $(REMOVE) $(DEPS) - $(REMOVE) comptime.h - -clean: - $(REMOVE) *~ *.flc - $(REMOVE) $(OBJDIR)/*.o - -distclean: clean cleandep - -ifdef MINGW - $(REMOVE) $(OBJDIR)/*.res -endif - -ifdef CYGWIN32 - $(REMOVE) $(OBJDIR)/*.res -endif - -#make a big srb2.s that is the disasm of the exe (dos only ?) -asm: - $(CC) $(LDFLAGS) $(OBJS) -o $(OBJDIR)/tmp.exe $(LIBS) - $(OBJDUMP) -d $(OBJDIR)/tmp.exe --no-show-raw-insn > srb2.s - $(REMOVE) $(OBJDIR)/tmp.exe - -# executable -# NOTE: DJGPP's objcopy do not have --add-gnu-debuglink - -$(BIN)/$(EXENAME): $(POS) $(OBJS) - -$(MKDIR) $(BIN) - $(call echo,Linking $(EXENAME)...) - $(LD) $(LDFLAGS) $(OBJS) -o $(BIN)/$(EXENAME) $(LIBS) -ifndef VALGRIND -ifndef NOOBJDUMP - $(call echo,Dumping debugging info) - $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt +# '::' means run unconditionally +# this really updates comptime.h +comptime.c :: ifdef WINDOWSHELL - -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt + $(.)..\comptime.bat . else - -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt -endif + $(.)../comptime.sh . endif -# mac os x lsdlsrb2 does not like objcopy -ifndef MACOSX - $(OBJCOPY) $(BIN)/$(EXENAME) $(BIN)/$(DBGNAME) - $(OBJCOPY) --strip-debug $(BIN)/$(EXENAME) - -$(OBJCOPY) --add-gnu-debuglink=$(BIN)/$(DBGNAME) $(BIN)/$(EXENAME) -endif -ifndef NOUPX - -$(UPX) $(UPX_OPTS) $(BIN)/$(EXENAME) -endif -endif - $(call echo,Build is done$(,) please look for $(EXENAME) in $(BIN)$(,) (checking for post steps)) +# I wish I could make dependencies out of rc files :( +$(objdir)/win32/Srb2win.res : \ + win32/afxres.h win32/resource.h -reobjdump: - $(call echo,Redumping debugging info) - $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt -ifdef WINDOWSHELL - -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt -else - -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt -endif - -$(OBJDIR): - -$(MKDIR) $(OBJDIR) - -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_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 - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -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_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 - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ -endif -endif - -#dependecy made by gcc itself ! -ifndef DUMMY -ifndef CLEANONLY -$(call print,Checking dependency files...) --include $(DEPS) -endif -endif - -undefine deps_rule - -# windows makes it too hard ! +# dependency recipe template +# 1: source file suffix +# 2: extra flags to gcc +define _recipe = +$(depdir)/%.d : %.$(1) | $$$$(@D)/ ifndef WINDOWSHELL -ifdef echoName -define deps_rule = - @printf "%-20.20s\r" $< - -endef +ifdef Echo_name + @printf '%-20.20s\r' $$< endif endif - -define deps_rule += - $(CC) $(CFLAGS) -M -MF $@ -MT $(OBJDIR)/$< $< + $(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$(*F).o $(2) $$< endef -$(DEPDIR)/%.d: %.c - $(deps_rule) +$(eval $(call _recipe,c)) +$(eval $(call _recipe,s,$(asflags))) -$(DEPDIR)/%.d: $(INTERFACE)/%.c - $(deps_rule) +# compiling recipe template +# 1: target file suffix +# 2: source file suffix +# 3: compile command +define _recipe = +$(objdir)/%.$(1) : %.$(2) | $$$$(@D)/ + $(call Echo_name,$$<) + $(.)$(3) +endef -$(DEPDIR)/%.d: hardware/%.c - $(deps_rule) +$(eval $(call _recipe,o,c,$(cc) -c -o $$@ $$<)) +$(eval $(call _recipe,o,nas,$(nasm) -o $$@ $$<)) +$(eval $(call _recipe,o,s,$(cc) $(asflags) -c -o $$@ $$<)) +$(eval $(call _recipe,res,rc,$(windres) -i $$< -o $$@)) -$(DEPDIR)/%.d: blua/%.c - $(deps_rule) +_rm=$(.)$(rmrf) $(call Windows_path,$(1)) -ifdef VALGRIND -$(OBJDIR)/z_zone.o: z_zone.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@ -endif +cleandep : + $(call _rm,$(depends) comptime.h) -$(OBJDIR)/comptime.o:: -ifdef echoName - @echo -- comptime.c ... -endif - $(COMPTIME) . - $(CC) $(CFLAGS) $(WFLAGS) -c comptime.c -o $@ +clean : + $(call _rm,$(exe) $(dbg) $(dbg).txt $(objects)) -$(BIN)/%.mo: locale/%.po - -$(MKDIR) $(BIN) - $(echoName) - $(MSGFMT) -f -o $@ $< +distclean : + $(call _rm,../bin ../objs ../deps ../make comptime.h) -$(OBJDIR)/%.o: %.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/%.o: $(INTERFACE)/%.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -ifdef MACOSX -$(OBJDIR)/%.o: sdl/macosx/%.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -endif - -$(OBJDIR)/%.o: hardware/%.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/%.o: blua/%.c - $(echoName) - $(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/%.o: %.nas - $(echoName) - $(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $< - -$(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc - $(echoName) - $(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@ - -$(OBJDIR)/%.o: %.s - $(echoName) - $(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@ - -$(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h - $(echoName) - $(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff - - -ifdef SDL - -ifdef MINGW -$(OBJDIR)/win_dbg.o: win32/win_dbg.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -endif - -ifdef STATICHS -$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -ifdef MINGW -$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -endif +info: +ifdef WINDOWSHELL + @REM else - -$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c - -$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c + @: endif -endif - -############################################################# -# -############################################################# diff --git a/src/Makefile.cfg b/src/Makefile.cfg deleted file mode 100644 index 075cd2d3a..000000000 --- a/src/Makefile.cfg +++ /dev/null @@ -1,478 +0,0 @@ -# vim: ft=make -# -# Makefile.cfg for SRB2 -# - -# -# GNU compiler & tools' flags -# and other things -# - -# See the following variable don't start with 'GCC'. This is -# to avoid a false positive with the version detection... - -SUPPORTED_GCC_VERSIONS:=\ - 101 102\ - 91 92 93\ - 81 82 83 84\ - 71 72 73 74 75\ - 61 62 63 64\ - 51 52 53 54 55\ - 40 41 42 43 44 45 46 47 48 49 - -LATEST_GCC_VERSION=10.2 - -# gcc or g++ -ifdef PREFIX - CC=$(PREFIX)-gcc - CXX=$(PREFIX)-g++ - OBJCOPY=$(PREFIX)-objcopy - OBJDUMP=$(PREFIX)-objdump - STRIP=$(PREFIX)-strip - WINDRES=$(PREFIX)-windres -else - OBJCOPY=objcopy - OBJDUMP=objdump - STRIP=strip - WINDRES=windres -endif - -# because Apple screws with us on this -# need to get bintools from homebrew -ifdef MACOSX - CC=clang - CXX=clang - OBJCOPY=gobjcopy - OBJDUMP=gobjdump -endif - -# Automatically set version flag, but not if one was manually set -# And don't bother if this is a clean only run -ifeq (,$(filter GCC% CLEANONLY,$(.VARIABLES))) - version:=$(shell $(CC) --version) - # check if this is in fact GCC - ifneq (,$(or $(findstring gcc,$(version)),$(findstring GCC,$(version)))) - version:=$(shell $(CC) -dumpversion) - - # Turn version into words of major, minor - v:=$(subst ., ,$(version)) - # concat. major minor - v:=$(word 1,$(v))$(word 2,$(v)) - - # If this version is not in the list, default to the latest supported - ifeq (,$(filter $(v),$(SUPPORTED_GCC_VERSIONS))) - define line = - Your compiler version, GCC $(version), is not supported by the Makefile. - The Makefile will assume GCC $(LATEST_GCC_VERSION).)) - endef - $(call print,$(line)) - GCC$(subst .,,$(LATEST_GCC_VERSION))=1 - else - $(call print,Detected GCC $(version) (GCC$(v))) - GCC$(v)=1 - endif - endif -endif - -ifdef GCC102 -GCC101=1 -endif - -ifdef GCC101 -GCC93=1 -endif - -ifdef GCC93 -GCC92=1 -endif - -ifdef GCC92 -GCC91=1 -endif - -ifdef GCC91 -GCC84=1 -endif - -ifdef GCC84 -GCC83=1 -endif - -ifdef GCC83 -GCC82=1 -endif - -ifdef GCC82 -GCC81=1 -endif - -ifdef GCC81 -GCC75=1 -endif - -ifdef GCC75 -GCC74=1 -endif - -ifdef GCC74 -GCC73=1 -endif - -ifdef GCC73 -GCC72=1 -endif - -ifdef GCC72 -GCC71=1 -endif - -ifdef GCC71 -GCC64=1 -endif - -ifdef GCC64 -GCC63=1 -endif - -ifdef GCC63 -GCC62=1 -endif - -ifdef GCC62 -GCC61=1 -endif - -ifdef GCC61 -GCC55=1 -endif - -ifdef GCC55 -GCC54=1 -endif - -ifdef GCC54 -GCC53=1 -endif - -ifdef GCC53 -GCC52=1 -endif - -ifdef GCC52 -GCC51=1 -endif - -ifdef GCC51 -GCC49=1 -endif - -ifdef GCC49 -GCC48=1 -endif - -ifdef GCC48 -GCC47=1 -endif - -ifdef GCC47 -GCC46=1 -endif - -ifdef GCC46 -GCC45=1 -endif - -ifdef GCC45 -GCC44=1 -endif - -ifdef GCC44 -GCC43=1 -endif - -ifdef GCC43 -GCC42=1 -endif - -ifdef GCC42 -GCC41=1 -endif - -ifdef GCC41 -GCC40=1 -VCHELP=1 -endif - -ifdef GCC295 -GCC29=1 -endif - -OLDWFLAGS:=$(WFLAGS) -# -W -Wno-unused -WFLAGS=-Wall -ifndef GCC295 -#WFLAGS+=-Wno-packed -endif -ifndef RELAXWARNINGS - WFLAGS+=-W -#WFLAGS+=-Wno-sign-compare -ifndef GCC295 - WFLAGS+=-Wno-div-by-zero -endif -#WFLAGS+=-Wsystem-headers -WFLAGS+=-Wfloat-equal -#WFLAGS+=-Wtraditional -ifdef VCHELP - WFLAGS+=-Wdeclaration-after-statement - WFLAGS+=-Wno-error=declaration-after-statement -endif - WFLAGS+=-Wundef -ifndef GCC295 - WFLAGS+=-Wendif-labels -endif -ifdef GCC41 - WFLAGS+=-Wshadow -endif -#WFLAGS+=-Wlarger-than-%len% - WFLAGS+=-Wpointer-arith -Wbad-function-cast -ifdef GCC45 -#WFLAGS+=-Wc++-compat -endif - WFLAGS+=-Wcast-qual -ifndef NOCASTALIGNWARN - WFLAGS+=-Wcast-align -endif - WFLAGS+=-Wwrite-strings -ifndef ERRORMODE -#WFLAGS+=-Wconversion -ifdef GCC43 - #WFLAGS+=-Wno-sign-conversion -endif -endif - WFLAGS+=-Wsign-compare -ifdef GCC91 - WFLAGS+=-Wno-error=address-of-packed-member -endif -ifdef GCC45 - WFLAGS+=-Wlogical-op -endif - WFLAGS+=-Waggregate-return -ifdef HAIKU -ifdef GCC41 - #WFLAGS+=-Wno-attributes -endif -endif -#WFLAGS+=-Wstrict-prototypes -ifdef GCC40 - WFLAGS+=-Wold-style-definition -endif - WFLAGS+=-Wmissing-prototypes -Wmissing-declarations -ifdef GCC40 - WFLAGS+=-Wmissing-field-initializers -endif - WFLAGS+=-Wmissing-noreturn -#WFLAGS+=-Wmissing-format-attribute -#WFLAGS+=-Wno-multichar -#WFLAGS+=-Wno-deprecated-declarations -#WFLAGS+=-Wpacked -#WFLAGS+=-Wpadded -#WFLAGS+=-Wredundant-decls - WFLAGS+=-Wnested-externs -#WFLAGS+=-Wunreachable-code - WFLAGS+=-Winline -ifdef GCC43 - WFLAGS+=-funit-at-a-time - WFLAGS+=-Wlogical-op -endif -ifndef GCC295 - WFLAGS+=-Wdisabled-optimization -endif -endif -WFLAGS+=-Wformat-y2k -ifdef GCC71 -WFLAGS+=-Wno-error=format-overflow=2 -endif -WFLAGS+=-Wformat-security -ifndef GCC29 -#WFLAGS+=-Winit-self -endif -ifdef GCC46 -WFLAGS+=-Wno-suggest-attribute=noreturn -endif - -ifdef NOLDWARNING -LDFLAGS+=-Wl,--as-needed -endif - -ifdef ERRORMODE -WFLAGS+=-Werror -endif - -WFLAGS+=$(OLDWFLAGS) - -ifdef GCC43 - #WFLAGS+=-Wno-error=clobbered -endif -ifdef GCC44 - WFLAGS+=-Wno-error=array-bounds -endif -ifdef GCC46 - WFLAGS+=-Wno-error=suggest-attribute=noreturn -endif -ifdef GCC54 - WFLAGS+=-Wno-logical-op -Wno-error=logical-op -endif -ifdef GCC61 - WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare -endif -ifdef GCC71 - WFLAGS+=-Wimplicit-fallthrough=4 -endif -ifdef GCC81 - WFLAGS+=-Wno-error=format-overflow - WFLAGS+=-Wno-error=stringop-truncation - WFLAGS+=-Wno-error=stringop-overflow - WFLAGS+=-Wno-format-overflow - WFLAGS+=-Wno-stringop-truncation - WFLAGS+=-Wno-stringop-overflow - WFLAGS+=-Wno-error=multistatement-macros -endif - - -#indicate platform and what interface use with -ifndef LINUX -ifndef FREEBSD -ifndef CYGWIN32 -ifndef MINGW -ifndef MINGW64 -ifndef SDL -ifndef DUMMY -$(error No interface or platform flag defined) -endif -endif -endif -endif -endif -endif -endif - -#determine the interface directory (where you put all i_*.c) -i_net_o=$(OBJDIR)/i_net.o -i_system_o=$(OBJDIR)/i_system.o -i_sound_o=$(OBJDIR)/i_sound.o -i_main_o=$(OBJDIR)/i_main.o -#set OBJDIR and BIN's starting place -OBJDIR=../objs -BIN=../bin -DEPDIR=../dep -#Nasm ASM and rm -ifdef YASM -NASM?=yasm -else -NASM?=nasm -endif -REMOVE?=rm -f -MKDIR?=mkdir -p -GZIP?=gzip -GZIP_OPTS?=-9 -f -n -GZIP_OPT2=$(GZIP_OPTS) --rsyncable -UPX?=upx -UPX_OPTS?=--best --preserve-build-id -ifndef ECHO -UPX_OPTS+=-q -endif - -#Interface Setup -ifdef DUMMY - INTERFACE=dummy - OBJDIR:=$(OBJDIR)/dummy - BIN:=$(BIN)/dummy - DEPDIR:=$(DEPDIR)/dummy -else -ifdef LINUX - NASMFORMAT=elf -DLINUX - SDL=1 -ifdef LINUX64 - OBJDIR:=$(OBJDIR)/Linux64 - BIN:=$(BIN)/Linux64 - DEPDIR:=$(DEPDIR)/Linux64 -else - OBJDIR:=$(OBJDIR)/Linux - BIN:=$(BIN)/Linux - DEPDIR:=$(DEPDIR)/Linux -endif -else -ifdef FREEBSD - INTERFACE=sdl - NASMFORMAT=elf -DLINUX - SDL=1 - - OBJDIR:=$(OBJDIR)/FreeBSD - BIN:=$(BIN)/FreeBSD - DEPDIR:=$(DEPDIR)/Linux -else -ifdef SOLARIS - INTERFACE=sdl - NASMFORMAT=elf -DLINUX - SDL=1 - - OBJDIR:=$(OBJDIR)/Solaris - BIN:=$(BIN)/Solaris - DEPDIR:=$(DEPDIR)/Solaris -else -ifdef CYGWIN32 - INTERFACE=sdl - NASMFORMAT=win32 - SDL=1 - - OBJDIR:=$(OBJDIR)/cygwin - BIN:=$(BIN)/Cygwin - DEPDIR:=$(DEPDIR)/Cygwin -else -ifdef MINGW64 - #NASMFORMAT=win64 - SDL=1 - OBJDIR:=$(OBJDIR)/Mingw64 - BIN:=$(BIN)/Mingw64 - DEPDIR:=$(DEPDIR)/Mingw64 -else -ifdef MINGW - NASMFORMAT=win32 - SDL=1 - OBJDIR:=$(OBJDIR)/Mingw - BIN:=$(BIN)/Mingw - DEPDIR:=$(DEPDIR)/Mingw -endif -endif -endif -endif -endif -endif -endif - -ifdef ARCHNAME - OBJDIR:=$(OBJDIR)/$(ARCHNAME) - BIN:=$(BIN)/$(ARCHNAME) - DEPDIR:=$(DEPDIR)/$(ARCHNAME) -endif - -OBJDUMP_OPTS?=--wide --source --line-numbers -LD=$(CC) - -ifdef SDL - INTERFACE=sdl - OBJDIR:=$(OBJDIR)/SDL - DEPDIR:=$(DEPDIR)/SDL -endif - -ifndef DUMMY -ifdef DEBUGMODE - OBJDIR:=$(OBJDIR)/Debug - BIN:=$(BIN)/Debug - DEPDIR:=$(DEPDIR)/Debug -else - OBJDIR:=$(OBJDIR)/Release - BIN:=$(BIN)/Release - DEPDIR:=$(DEPDIR)/Release -endif -endif diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk new file mode 100644 index 000000000..3edf0dad4 --- /dev/null +++ b/src/Makefile.d/detect.mk @@ -0,0 +1,107 @@ +# +# Detect the host system and compiler version. +# + +# Previously featured:\ + PANDORA\ + HAIKU\ + DUMMY\ + DJGPPDOS\ + SOLARIS\ + MACOSX\ + +all_systems:=\ + LINUX64\ + MINGW64\ + MINGW\ + UNIX\ + LINUX\ + FREEBSD\ + SDL\ + +# check for user specified system +ifeq (,$(filter $(all_systems),$(.VARIABLES))) +ifeq ($(OS),Windows_NT) # all windows are Windows_NT... + +_m=Detected a Windows system,\ + compiling for 32-bit MinGW SDL...) +$(call Print,$(_m)) + +# go for a 32-bit sdl mingw exe by default +MINGW:=1 +# cmd.exe uses native Windows semicolon delimited PATH +ifneq (,$(findstring ;,$(PATH))) +WINDOWSHELL:=1 +endif + +else # if you on the *nix + +system:=$(shell uname -s) + +ifeq ($(system),Linux) +new_system:=LINUX +else + +$(error \ + Could not automatically detect your system,\ + try specifying a system manually) + +endif + +ifeq ($(shell getconf LONG_BIT),64) +system+=64-bit +new_system:=$(new_system)64 +endif + +$(call Print,Detected $(system) ($(new_system))...) +$(new_system):=1 + +endif +endif + +# This must have high to low order. +gcc_versions:=\ + 102 101\ + 93 92 91\ + 84 83 82 81\ + 75 74 73 72 71\ + 64 63 62 61\ + 55 54 53 52 51\ + 49 48 47 46 45 44 43 42 41 40 + +latest_gcc_version:=10.2 + +# Automatically set version flag, but not if one was +# manually set. And don't bother if this is a clean only +# run. +ifeq (,$(call Wildvar,GCC% destructive)) +version:=$(shell $(CC) --version) + +# check if this is in fact GCC +ifneq (,$(or $(findstring gcc,$(version)),\ + $(findstring GCC,$(version)))) + +version:=$(shell $(CC) -dumpversion) + +# Turn version into words of major, minor +v:=$(subst ., ,$(version)) +# concat. major minor +v:=$(word 1,$(v))$(word 2,$(v)) + +# If this version is not in the list, +# default to the latest supported +ifeq (,$(filter $(v),$(gcc_versions))) +define line = +Your compiler version, GCC $(version), \ +is not supported by the Makefile. +The Makefile will assume GCC $(latest_gcc_version). +endef +$(call Print,$(line)) +GCC$(subst .,,$(latest_gcc_version)):=1 +else +$(call Print,Detected GCC $(version) (GCC$(v))) +GCC$(v):=1 +endif + +endif +endif diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk new file mode 100644 index 000000000..46194390d --- /dev/null +++ b/src/Makefile.d/features.mk @@ -0,0 +1,75 @@ +# +# Makefile for feature flags. +# + +passthru_opts+=\ + NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\ + MOBJCONSISTANCY PACKETDROP ZDEBUG\ + HAVE_MINIUPNPC\ + +# build with debugging information +ifdef DEBUGMODE +PACKETDROP=1 +opts+=-DPARANOIA -DRANGECHECK +endif + +ifndef NOHW +opts+=-DHWRENDER +sources+=$(call List,hardware/Sourcefile) +endif + +ifndef NOASM +ifndef NONX86 +sources+=tmap.nas tmap_mmx.nas +opts+=-DUSEASM +endif +endif + +ifndef NOMD5 +sources+=md5.c +endif + +ifndef NOZLIB +ifndef NOPNG +ifdef PNG_PKGCONFIG +$(eval $(call Use_pkg_config,PNG_PKGCONFIG)) +else +PNG_CONFIG?=$(call Prefix,libpng-config) +$(eval $(call Configure,PNG,$(PNG_CONFIG) \ + $(if $(PNG_STATIC),--static),,--ldflags)) +endif +ifdef LINUX +opts+=-D_LARGFILE64_SOURCE +endif +opts+=-DHAVE_PNG +sources+=apng.c +endif +endif + +ifndef NONET +ifndef NOCURL +CURLCONFIG?=curl-config +$(eval $(call Configure,CURL,$(CURLCONFIG))) +opts+=-DHAVE_CURL +endif +endif + +ifdef HAVE_MINIUPNPC +libs+=-lminiupnpc +endif + +# (Valgrind is a memory debugger.) +ifdef VALGRIND +VALGRIND_PKGCONFIG?=valgrind +$(eval $(call Use_pkg_config,VALGRIND)) +ZDEBUG=1 +opts+=-DHAVE_VALGRIND +endif + +default_packages:=\ + GME/libgme/LIBGME\ + OPENMPT/libopenmpt/LIBOPENMPT\ + ZLIB/zlib\ + +$(foreach p,$(default_packages),\ + $(eval $(call Check_pkg_config,$(p)))) diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk new file mode 100644 index 000000000..6642a6bcc --- /dev/null +++ b/src/Makefile.d/nix.mk @@ -0,0 +1,42 @@ +# +# Makefile options for unices (linux, bsd...) +# + +EXENAME?=lsdl2srb2 + +opts+=-DUNIXCOMMON -DLUA_USE_POSIX +# Use -rdynamic so a backtrace log shows function names +# instead of addresses +libs+=-lm -rdynamic + +ifndef nasm_format +nasm_format:=elf -DLINUX +endif + +ifndef NOHW +opts+=-I/usr/X11R6/include +libs+=-L/usr/X11R6/lib +endif + +SDL=1 + +# In common usage. +ifdef LINUX +libs+=-lrt +passthru_opts+=NOTERMIOS +endif + +# Tested by Steel, as of release 2.2.8. +ifdef FREEBSD +opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD +libs+=-L/usr/X11R6/lib -lipx -lkvm +endif + +# FIXME: UNTESTED +#ifdef SOLARIS +#NOIPX=1 +#NOASM=1 +#opts+=-I/usr/local/include -I/opt/sfw/include \ +# -DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP +#libs+=-L/opt/sfw/lib -lsocket -lnsl +#endif diff --git a/src/Makefile.d/old.mk b/src/Makefile.d/old.mk new file mode 100644 index 000000000..e5890eedd --- /dev/null +++ b/src/Makefile.d/old.mk @@ -0,0 +1,16 @@ +# +# Warn about old build directories and offer to purge. +# + +_old:=$(wildcard $(addprefix ../bin/,FreeBSD Linux \ + Linux64 Mingw Mingw64 SDL dummy) ../objs ../deps) + +ifdef _old +$(foreach v,$(_old),$(info $(abspath $(v)))) +$(info ) +$(info These directories are no longer\ + required and should be removed.) +$(info You may remove them manually or\ + by using 'make distclean') +$(error ) +endif diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk new file mode 100644 index 000000000..fad4be191 --- /dev/null +++ b/src/Makefile.d/platform.mk @@ -0,0 +1,69 @@ +# +# Platform specific options. +# + +PKG_CONFIG?=pkg-config + +ifdef WINDOWSHELL +rmrf=-2>NUL DEL /S /Q +mkdir=-2>NUL MD +cat=TYPE +else +rmrf=rm -rf +mkdir=mkdir -p +cat=cat +endif + +ifdef LINUX64 +LINUX=1 +endif + +ifdef MINGW64 +MINGW=1 +endif + +ifdef LINUX +UNIX=1 +ifdef LINUX64 +NONX86=1 +# LINUX64 does not imply X86_64=1; +# could mean ARM64 or Itanium +platform=linux/64 +else +platform=linux +endif +else ifdef FREEBSD +UNIX=1 +platform=freebsd +else ifdef SOLARIS # FIXME: UNTESTED +UNIX=1 +platform=solaris +else ifdef CYGWIN32 # FIXME: UNTESTED +nasm_format=win32 +platform=cygwin +else ifdef MINGW +ifdef MINGW64 +NONX86=1 +NOASM=1 +# MINGW64 should not necessarily imply X86_64=1, +# but we make that assumption elsewhere +# Once that changes, remove this +X86_64=1 +platform=mingw/64 +else +platform=mingw +endif +include Makefile.d/win32.mk +endif + +ifdef platform +makedir:=$(makedir)/$(platform) +endif + +ifdef UNIX +include Makefile.d/nix.mk +endif + +ifdef SDL +include Makefile.d/sdl.mk +endif diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk new file mode 100644 index 000000000..99ca624e6 --- /dev/null +++ b/src/Makefile.d/sdl.mk @@ -0,0 +1,79 @@ +# +# Makefile options for SDL2 backend. +# + +# +# SDL...., *looks at Alam*, THIS IS A MESS! +# +# ...a little bird flexes its muscles... +# + +makedir:=$(makedir)/SDL + +sources+=$(call List,sdl/Sourcefile) +opts+=-DDIRECTFULLSCREEN -DHAVE_SDL + +# FIXME: UNTESTED +#ifdef PANDORA +#include sdl/SRB2Pandora/Makefile.cfg +#endif #ifdef PANDORA + +# FIXME: UNTESTED +#ifdef CYGWIN32 +#include sdl/MakeCYG.cfg +#endif #ifdef CYGWIN32 + +ifndef NOHW +sources+=sdl/ogl_sdl.c +endif + +ifdef NOMIXER +sources+=sdl/sdl_sound.c +else +opts+=-DHAVE_MIXER +sources+=sdl/mixer_sound.c + + ifdef HAVE_MIXERX + opts+=-DHAVE_MIXERX + libs+=-lSDL2_mixer_ext + else + libs+=-lSDL2_mixer + endif +endif + +ifndef NOTHREADS +opts+=-DHAVE_THREADS +sources+=sdl/i_threads.c +endif + +ifdef SDL_PKGCONFIG +$(eval $(call Use_pkg_config,SDL)) +else +SDL_CONFIG?=$(call Prefix,sdl2-config) +SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) +SDL_LDFLAGS?=$(shell $(SDL_CONFIG) \ + $(if $(STATIC),--static-libs,--libs)) +$(eval $(call Propogate_flags,SDL)) +endif + +# use the x86 asm code +ifndef CYGWIN32 +ifndef NOASM +USEASM=1 +endif +endif + +ifdef MINGW +ifndef NOSDLMAIN +SDLMAIN=1 +endif +endif + +ifdef SDLMAIN +opts+=-DSDLMAIN +else +ifdef MINGW +opts+=-Umain +libs+=-mconsole +endif +endif diff --git a/src/Makefile.d/util.mk b/src/Makefile.d/util.mk new file mode 100644 index 000000000..bda68df13 --- /dev/null +++ b/src/Makefile.d/util.mk @@ -0,0 +1,93 @@ +# +# Utility macros for the rest of the Makefiles. +# + +Ifnot=$(if $(1),$(3),$(2)) +Ifndef=$(call Ifnot,$($(1)),$(2),$(3)) + +# Match and expand a list of variables by pattern. +Wildvar=$(foreach v,$(filter $(1),$(.VARIABLES)),$($(v))) + +# Read a list of words from file and prepend each with the +# directory of the file. +_cat=$(shell $(cat) $(call Windows_path,$(1))) +List=$(addprefix $(dir $(1)),$(call _cat,$(1))) + +# Convert path separators to backslash on Windows. +Windows_path=$(if $(WINDOWSHELL),$(subst /,\,$(1)),$(1)) + +define Propogate_flags = +opts+=$$($(1)_CFLAGS) +libs+=$$($(1)_LDFLAGS) +endef + +# Set library's _CFLAGS and _LDFLAGS from some command. +# Automatically propogates the flags too. +# 1: variable prefix (e.g. CURL) +# 2: start of command (e.g. curl-config) +# --- optional ---- +# 3: CFLAGS command arguments, default '--cflags' +# 4: LDFLAGS command arguments, default '--libs' +# 5: common command arguments at the end of command +define Configure = +$(1)_CFLAGS?=$$(shell $(2) $(or $(3),--cflags) $(5)) +$(1)_LDFLAGS?=$$(shell $(2) $(or $(4),--libs) $(5)) +$(call Propogate_flags,$(1)) +endef + +# Configure library with pkg-config. The package name is +# taken from a _PKGCONFIG variable. +# 1: variable prefix +# +# LIBGME_PKGCONFIG=libgme +# $(eval $(call Use_pkg_config,LIBGME)) +define Use_pkg_config = +$(call Configure,$(1),$(PKG_CONFIG),,,$($(1)_PKGCONFIG)) +endef + +# Check disabling flag and configure package in one step +# according to delimited argument. +# (There is only one argument, but it split by slash.) +# 1/: short form library name (uppercase). This is +# prefixed with 'NO' and 'HAVE_'. E.g. NOGME, HAVE_GME +# /2: package name (e.g. libgme) +# /3: variable prefix +# +# The following example would check if NOGME is not +# defined before attempting to define LIBGME_CFLAGS and +# LIBGME_LDFLAGS as with Use_pkg_config. +# +# $(eval $(call Check_pkg_config,GME/libgme/LIBGME)) +define Check_pkg_config = +_p:=$(subst /, ,$(1)) +_v1:=$$(word 1,$$(_p)) +_v2:=$$(or $$(word 3,$$(_p)),$$(_v1)) +ifndef NO$$(_v1) +$$(_v2)_PKGCONFIG?=$$(word 2,$$(_p)) +$$(eval $$(call Use_pkg_config,$$(_v2))) +opts+=-DHAVE_$$(_v1) +endif +endef + +# $(call Prefix,gcc) +Prefix=$(if $(PREFIX),$(PREFIX)-)$(1) + +Echo= +Echo_name= +Print= + +ifndef SILENT +Echo=@echo $(1) +ifndef ECHO +ifndef NOECHOFILENAMES +Echo_name=$(call Echo,-- $(1) ...) +endif +endif +ifndef MAKE_RESTARTS +ifndef destructive +Print=$(info $(1)) +endif +endif +endif + +.=$(call Ifndef,ECHO,@) diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk new file mode 100644 index 000000000..d7d0c3dd1 --- /dev/null +++ b/src/Makefile.d/versions.mk @@ -0,0 +1,177 @@ +# +# Flags to put a sock in GCC! +# + +# See the versions list in detect.mk +# This will define all version flags going backward. +# Yes, it's magic. +define _predecessor = +ifdef GCC$(firstword $(1)) +GCC$(lastword $(1)):=1 +endif +endef +_n:=$(words $(gcc_versions)) +$(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\ + $(addprefix =,$(wordlist 2,$(_n),$(gcc_versions)))),\ + $(and $(findstring =,$(v)),\ + $(eval $(call _predecessor,$(subst =, ,$(v)))))) + +# -W -Wno-unused +WFLAGS:=-Wall -Wno-trigraphs +ifndef GCC295 +#WFLAGS+=-Wno-packed +endif +ifndef RELAXWARNINGS + WFLAGS+=-W +#WFLAGS+=-Wno-sign-compare +ifndef GCC295 + WFLAGS+=-Wno-div-by-zero +endif +#WFLAGS+=-Wsystem-headers +WFLAGS+=-Wfloat-equal +#WFLAGS+=-Wtraditional + WFLAGS+=-Wundef +ifndef GCC295 + WFLAGS+=-Wendif-labels +endif +ifdef GCC41 + WFLAGS+=-Wdeclaration-after-statement + WFLAGS+=-Wno-error=declaration-after-statement + WFLAGS+=-Wshadow +endif +#WFLAGS+=-Wlarger-than-%len% + WFLAGS+=-Wpointer-arith -Wbad-function-cast +ifdef GCC45 +#WFLAGS+=-Wc++-compat +endif + WFLAGS+=-Wcast-qual +ifndef NOCASTALIGNWARN + WFLAGS+=-Wcast-align +endif + WFLAGS+=-Wwrite-strings +ifndef ERRORMODE +#WFLAGS+=-Wconversion +ifdef GCC43 + #WFLAGS+=-Wno-sign-conversion +endif +endif + WFLAGS+=-Wsign-compare +ifdef GCC91 + WFLAGS+=-Wno-error=address-of-packed-member +endif +ifdef GCC45 + WFLAGS+=-Wlogical-op +endif + WFLAGS+=-Waggregate-return +ifdef HAIKU +ifdef GCC41 + #WFLAGS+=-Wno-attributes +endif +endif +#WFLAGS+=-Wstrict-prototypes +ifdef GCC40 + WFLAGS+=-Wold-style-definition +endif + WFLAGS+=-Wmissing-prototypes -Wmissing-declarations +ifdef GCC40 + WFLAGS+=-Wmissing-field-initializers +endif + WFLAGS+=-Wmissing-noreturn +#WFLAGS+=-Wmissing-format-attribute +#WFLAGS+=-Wno-multichar +#WFLAGS+=-Wno-deprecated-declarations +#WFLAGS+=-Wpacked +#WFLAGS+=-Wpadded +#WFLAGS+=-Wredundant-decls + WFLAGS+=-Wnested-externs +#WFLAGS+=-Wunreachable-code + WFLAGS+=-Winline +ifdef GCC43 + WFLAGS+=-funit-at-a-time + WFLAGS+=-Wlogical-op +endif +ifndef GCC295 + WFLAGS+=-Wdisabled-optimization +endif +endif +WFLAGS+=-Wformat-y2k +ifdef GCC71 +WFLAGS+=-Wno-error=format-overflow=2 +endif +WFLAGS+=-Wformat-security +ifndef GCC29 +#WFLAGS+=-Winit-self +endif +ifdef GCC46 +WFLAGS+=-Wno-suggest-attribute=noreturn +endif + +ifdef NOLDWARNING +LDFLAGS+=-Wl,--as-needed +endif + +ifdef ERRORMODE +WFLAGS+=-Werror +endif + +ifdef GCC43 + #WFLAGS+=-Wno-error=clobbered +endif +ifdef GCC44 + WFLAGS+=-Wno-error=array-bounds +endif +ifdef GCC46 + WFLAGS+=-Wno-error=suggest-attribute=noreturn +endif +ifdef GCC54 + WFLAGS+=-Wno-logical-op -Wno-error=logical-op +endif +ifdef GCC61 + WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare +endif +ifdef GCC71 + WFLAGS+=-Wimplicit-fallthrough=4 +endif +ifdef GCC81 + WFLAGS+=-Wno-error=format-overflow + WFLAGS+=-Wno-error=stringop-truncation + WFLAGS+=-Wno-error=stringop-overflow + WFLAGS+=-Wno-format-overflow + WFLAGS+=-Wno-stringop-truncation + WFLAGS+=-Wno-stringop-overflow + WFLAGS+=-Wno-error=multistatement-macros +endif + +ifdef NONX86 + ifdef X86_64 # yeah that SEEMS contradictory + opts+=-march=nocona + endif +else + ifndef GCC29 + opts+=-msse3 -mfpmath=sse + else + opts+=-mpentium + endif +endif + +ifdef DEBUGMODE +ifdef GCC48 +opts+=-Og +else +opts+=O0 +endif +endif + +ifdef VALGRIND +ifdef GCC46 +WFLAGS+=-Wno-error=unused-but-set-variable +WFLAGS+=-Wno-unused-but-set-variable +endif +endif + +# Lua +ifdef GCC43 +ifndef GCC44 +WFLAGS+=-Wno-logical-op +endif +endif diff --git a/src/Makefile.d/win32.mk b/src/Makefile.d/win32.mk new file mode 100644 index 000000000..0c671b268 --- /dev/null +++ b/src/Makefile.d/win32.mk @@ -0,0 +1,99 @@ +# +# Mingw, if you don't know, that's Win32/Win64 +# + +ifndef MINGW64 +EXENAME?=srb2win.exe +else +EXENAME?=srb2win64.exe +endif + +sources+=win32/Srb2win.rc +opts+=-DSTDC_HEADERS +libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 + +nasm_format:=win32 + +SDL=1 + +ifndef NOHW +opts+=-DUSE_WGL_SWAP +endif + +ifdef MINGW64 +libs+=-lws2_32 +else +ifdef NO_IPV6 +libs+=-lwsock32 +else +libs+=-lws2_32 +endif +endif + +ifndef NONET +ifndef MINGW64 # miniupnc is broken with MINGW64 +opts+=-I../libs -DSTATIC_MINIUPNPC +libs+=-L../libs/miniupnpc/mingw$(32) -lws2_32 -liphlpapi +endif +endif + +ifndef MINGW64 +32=32 +x86=x86 +i686=i686 +else +32=64 +x86=x86_64 +i686=x86_64 +endif + +mingw:=$(i686)-w64-mingw32 + +define _set = +$(1)_CFLAGS?=$($(1)_opts) +$(1)_LDFLAGS?=$($(1)_libs) +endef + +lib:=../libs/gme +LIBGME_opts:=-I$(lib)/include +LIBGME_libs:=-L$(lib)/win$(32) -lgme +$(eval $(call _set,LIBGME)) + +lib:=../libs/libopenmpt +LIBOPENMPT_opts:=-I$(lib)/inc +LIBOPENMPT_libs:=-L$(lib)/lib/$(x86)/mingw -lopenmpt +$(eval $(call _set,LIBOPENMPT)) + +ifndef NOMIXERX +HAVE_MIXERX=1 +lib:=../libs/SDLMixerX/$(mingw) +else +lib:=../libs/SDL2_mixer/$(mingw) +endif + +mixer_opts:=-I$(lib)/include/SDL2 +mixer_libs:=-L$(lib)/lib + +lib:=../libs/SDL2/$(mingw) +SDL_opts:=-I$(lib)/include/SDL2\ + $(mixer_opts) -Dmain=SDL_main +SDL_libs:=-L$(lib)/lib $(mixer_libs)\ + -lmingw32 -lSDL2main -lSDL2 -mwindows +$(eval $(call _set,SDL)) + +lib:=../libs/zlib +ZLIB_opts:=-I$(lib) +ZLIB_libs:=-L$(lib)/win32 -lz$(32) +$(eval $(call _set,ZLIB)) + +ifndef PNG_CONFIG +lib:=../libs/libpng-src +PNG_opts:=-I$(lib) +PNG_libs:=-L$(lib)/projects -lpng$(32) +$(eval $(call _set,PNG)) +endif + +lib:=../libs/curl +CURL_opts:=-I$(lib)/include +CURL_libs:=-L$(lib)/lib$(32) -lcurl +$(eval $(call _set,CURL)) diff --git a/src/Sourcefile b/src/Sourcefile new file mode 100644 index 000000000..983dadaf0 --- /dev/null +++ b/src/Sourcefile @@ -0,0 +1,98 @@ +string.c +d_main.c +d_clisrv.c +d_net.c +d_netfil.c +d_netcmd.c +dehacked.c +deh_soc.c +deh_lua.c +deh_tables.c +z_zone.c +f_finale.c +f_wipe.c +g_demo.c +g_game.c +g_input.c +am_map.c +command.c +console.c +hu_stuff.c +y_inter.c +st_stuff.c +m_aatree.c +m_anigif.c +m_argv.c +m_bbox.c +m_cheat.c +m_cond.c +m_easing.c +m_fixed.c +m_menu.c +m_misc.c +m_perfstats.c +m_random.c +m_queue.c +info.c +p_ceilng.c +p_enemy.c +p_floor.c +p_inter.c +p_lights.c +p_map.c +p_maputl.c +p_mobj.c +p_polyobj.c +p_saveg.c +p_setup.c +p_sight.c +p_spec.c +p_telept.c +p_tick.c +p_user.c +p_slopes.c +tables.c +r_bsp.c +r_data.c +r_draw.c +r_main.c +r_plane.c +r_segs.c +r_skins.c +r_sky.c +r_splats.c +r_things.c +r_textures.c +r_patch.c +r_patchrotation.c +r_picformats.c +r_portal.c +screen.c +taglist.c +v_video.c +s_sound.c +sounds.c +w_wad.c +filesrch.c +mserv.c +http-mserv.c +i_tcp.c +lzf.c +vid_copy.s +b_bot.c +lua_script.c +lua_baselib.c +lua_mathlib.c +lua_hooklib.c +lua_consolelib.c +lua_infolib.c +lua_mobjlib.c +lua_playerlib.c +lua_skinlib.c +lua_thinkerlib.c +lua_maplib.c +lua_taglib.c +lua_polyobjlib.c +lua_blockmaplib.c +lua_hudlib.c +lua_inputlib.c diff --git a/src/am_map.c b/src/am_map.c index 53a7480a5..ef0ebb88c 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/am_map.h b/src/am_map.h index 1c8fa70e4..022a7208b 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/apng.c b/src/apng.c index 0abbe541d..36b205c60 100644 --- a/src/apng.c +++ b/src/apng.c @@ -1,5 +1,5 @@ /* -Copyright 2019-2020, James R. +Copyright 2019-2021, James R. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/apng.h b/src/apng.h index a8b5c8f24..893b523cb 100644 --- a/src/apng.h +++ b/src/apng.h @@ -1,5 +1,5 @@ /* -Copyright 2019-2020, James R. +Copyright 2019-2021, James R. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/asm_defs.inc b/src/asm_defs.inc index ec286b0bd..9074f20f8 100644 --- a/src/asm_defs.inc +++ b/src/asm_defs.inc @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/b_bot.c b/src/b_bot.c index d3635f32c..9213da95e 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2011-2020 by Sonic Team Junior. +// Copyright (C) 2011-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -75,7 +75,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) return; // Lua can handle it! - if (LUAh_BotAI(sonic, tails, cmd)) + if (LUA_HookBotAI(sonic, tails, cmd)) return; if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC) @@ -363,7 +363,7 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) CV_SetValue(&cv_analog[1], false); // Let Lua scripts build ticcmds - if (LUAh_BotTiccmd(player, cmd)) + if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd))) return; // We don't have any main character AI, sorry. D: @@ -461,7 +461,7 @@ boolean B_CheckRespawn(player_t *player) // B_RespawnBot doesn't do anything if the condition above this isn't met { - UINT8 shouldForce = LUAh_BotRespawn(sonic, tails); + UINT8 shouldForce = LUA_Hook2Mobj(sonic, tails, MOBJ_HOOK(BotRespawn)); if (P_MobjWasRemoved(sonic) || P_MobjWasRemoved(tails)) return (shouldForce == 1); // mobj was removed diff --git a/src/b_bot.h b/src/b_bot.h index 2806bd68f..9f55637d1 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/blua/CMakeLists.txt b/src/blua/CMakeLists.txt new file mode 100644 index 000000000..4e9c67d2f --- /dev/null +++ b/src/blua/CMakeLists.txt @@ -0,0 +1 @@ +target_sourcefile(c) diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg deleted file mode 100644 index 3a2962e65..000000000 --- a/src/blua/Makefile.cfg +++ /dev/null @@ -1,53 +0,0 @@ -ifdef UNIXCOMMON -LUA_CFLAGS+=-DLUA_USE_POSIX -endif -ifdef LINUX -LUA_CFLAGS+=-DLUA_USE_POSIX -endif -ifdef GCC43 -ifndef GCC44 -WFLAGS+=-Wno-logical-op -endif -endif - -OBJS:=$(OBJS) \ - $(OBJDIR)/lapi.o \ - $(OBJDIR)/lbaselib.o \ - $(OBJDIR)/ldo.o \ - $(OBJDIR)/lfunc.o \ - $(OBJDIR)/linit.o \ - $(OBJDIR)/liolib.o \ - $(OBJDIR)/llex.o \ - $(OBJDIR)/lmem.o \ - $(OBJDIR)/lobject.o \ - $(OBJDIR)/lstate.o \ - $(OBJDIR)/lstrlib.o \ - $(OBJDIR)/ltablib.o \ - $(OBJDIR)/lundump.o \ - $(OBJDIR)/lzio.o \ - $(OBJDIR)/lauxlib.o \ - $(OBJDIR)/lcode.o \ - $(OBJDIR)/ldebug.o \ - $(OBJDIR)/ldump.o \ - $(OBJDIR)/lgc.o \ - $(OBJDIR)/lopcodes.o \ - $(OBJDIR)/lparser.o \ - $(OBJDIR)/lstring.o \ - $(OBJDIR)/ltable.o \ - $(OBJDIR)/ltm.o \ - $(OBJDIR)/lvm.o \ - $(OBJDIR)/lua_script.o \ - $(OBJDIR)/lua_baselib.o \ - $(OBJDIR)/lua_mathlib.o \ - $(OBJDIR)/lua_hooklib.o \ - $(OBJDIR)/lua_consolelib.o \ - $(OBJDIR)/lua_infolib.o \ - $(OBJDIR)/lua_mobjlib.o \ - $(OBJDIR)/lua_playerlib.o \ - $(OBJDIR)/lua_skinlib.o \ - $(OBJDIR)/lua_thinkerlib.o \ - $(OBJDIR)/lua_maplib.o \ - $(OBJDIR)/lua_taglib.o \ - $(OBJDIR)/lua_polyobjlib.o \ - $(OBJDIR)/lua_blockmaplib.o \ - $(OBJDIR)/lua_hudlib.o diff --git a/src/blua/Sourcefile b/src/blua/Sourcefile new file mode 100644 index 000000000..f99c89c8d --- /dev/null +++ b/src/blua/Sourcefile @@ -0,0 +1,25 @@ +lapi.c +lbaselib.c +ldo.c +lfunc.c +linit.c +liolib.c +llex.c +lmem.c +lobject.c +lstate.c +lstrlib.c +ltablib.c +lundump.c +lzio.c +lauxlib.c +lcode.c +ldebug.c +ldump.c +lgc.c +lopcodes.c +lparser.c +lstring.c +ltable.c +ltm.c +lvm.c diff --git a/src/byteptr.h b/src/byteptr.h index 01a6293b4..4c8414fae 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/command.c b/src/command.c index 58434ef89..95b1fd67d 100644 --- a/src/command.c +++ b/src/command.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1433,6 +1433,7 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) if (var->revert.allocated) { Z_Free(var->revert.v.string); + var->revert.allocated = false; // the below value is not allocated in zone memory, don't try to free it! } var->revert.v.const_munge = var->PossibleValue[i].strvalue; @@ -1440,6 +1441,10 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) return; } + // free the old value string + Z_Free(var->zstring); + var->zstring = NULL; + var->value = var->PossibleValue[i].value; var->string = var->PossibleValue[i].strvalue; goto finish; @@ -1502,13 +1507,7 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) found: if (client && execversion_enabled) { - if (var->revert.allocated) - { - Z_Free(var->revert.v.string); - } - var->revert.v.const_munge = var->PossibleValue[i].strvalue; - return; } @@ -1523,6 +1522,7 @@ found: if (var->revert.allocated) { Z_Free(var->revert.v.string); + // Z_StrDup creates a new zone memory block, so we can keep the allocated flag on } var->revert.v.string = Z_StrDup(valstr); @@ -1577,7 +1577,7 @@ finish: } var->flags |= CV_MODIFIED; // raise 'on change' code - LUA_CVarChanged(var->name); // let consolelib know what cvar this is. + LUA_CVarChanged(var); // let consolelib know what cvar this is. if (var->flags & CV_CALL && !stealth) var->func(); @@ -1787,6 +1787,7 @@ void CV_RevertNetVars(void) if (cvar->revert.allocated) { Z_Free(cvar->revert.v.string); + cvar->revert.allocated = false; // no value being held now } cvar->revert.v.string = NULL; diff --git a/src/command.h b/src/command.h index d4033e6ef..34fd15963 100644 --- a/src/command.h +++ b/src/command.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/config.h.in b/src/config.h.in index a6f43a7d7..db794cccc 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -34,12 +34,13 @@ * Last updated 2020 / 07 / 10 - v2.2.6 - player.dta & patch.pk3 * Last updated 2020 / 09 / 27 - v2.2.7 - patch.pk3 * Last updated 2020 / 10 / 02 - v2.2.8 - patch.pk3 + * Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3 */ #define ASSET_HASH_SRB2_PK3 "0277c9416756627004e83cbb5b2e3e28" -#define ASSET_HASH_ZONES_PK3 "f7e88afb6af7996a834c7d663144bead" +#define ASSET_HASH_ZONES_PK3 "f8f3e2b5deacf40f14e36686a07d44bb" #define ASSET_HASH_PLAYER_DTA "49dad7b24634c89728cc3e0b689e12bb" #ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_PK3 "466cdf60075262b3f5baa5e07f0999e8" +#define ASSET_HASH_PATCH_PK3 "7d467a883f7887b3c311798ee2f56b6a" #endif #endif diff --git a/src/console.c b/src/console.c index 121605b10..b3c413840 100644 --- a/src/console.c +++ b/src/console.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -221,7 +221,7 @@ static void CONS_Bind_f(void) for (key = 0; key < NUMINPUTS; key++) if (bindtable[key]) { - CONS_Printf("%s : \"%s\"\n", G_KeynumToString(key), bindtable[key]); + CONS_Printf("%s : \"%s\"\n", G_KeyNumToString(key), bindtable[key]); na = 1; } if (!na) @@ -229,7 +229,7 @@ static void CONS_Bind_f(void) return; } - key = G_KeyStringtoNum(COM_Argv(1)); + key = G_KeyStringToNum(COM_Argv(1)); if (key <= 0 || key >= NUMINPUTS) { CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n")); @@ -1303,10 +1303,6 @@ boolean CON_Responder(event_t *ev) if (key < 32 || key > 127) return true; - // add key to cmd line here - if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers - key = key + 'a' - 'A'; - if (input_sel != input_cur) CON_InputDelSelection(); CON_InputAddChar(key); @@ -1701,7 +1697,10 @@ static void CON_DrawHudlines(void) { charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; p++; + c++; } + if (c >= con_width) + break; if (*p < HU_FONTSTART) ;//charwidth = 4 * con_scalefactor; else @@ -1822,7 +1821,10 @@ static void CON_DrawConsole(void) { charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; p++; + c++; } + if (c >= con_width) + break; V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } } diff --git a/src/console.h b/src/console.h index 0296f4f6e..28f40d308 100644 --- a/src/console.h +++ b/src/console.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3dfb5cea8..1549811c1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1565,15 +1565,6 @@ static void CL_LoadReceivedSavegame(boolean reloading) } CONS_Printf("\"\n"); } - else - { - CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); - Z_Free(savebuffer); - save_p = NULL; - if (unlink(tmpsave) == -1) - CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); - return; - } // done Z_Free(savebuffer); @@ -2545,14 +2536,14 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason) } } - LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting + LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting // don't look through someone's view who isn't there if (playernum == displayplayer) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); + LUA_HookViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -2961,7 +2952,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) { case KICK_MSG_GO_AWAY: if (!players[pnum].quittime) - HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false); + HU_AddChatText(va("\x82*%s has been kicked (No reason given)", player_names[pnum]), false); kickreason = KR_KICK; break; case KICK_MSG_PING_HIGH: @@ -2969,7 +2960,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) kickreason = KR_PINGLIMIT; break; case KICK_MSG_CON_FAIL: - HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false); + HU_AddChatText(va("\x82*%s left the game (Synch failure)", player_names[pnum]), false); kickreason = KR_SYNCH; if (M_CheckParm("-consisdump")) // Helps debugging some problems @@ -3015,7 +3006,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) kickreason = KR_LEAVE; break; case KICK_MSG_BANNED: - HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false); + HU_AddChatText(va("\x82*%s has been banned (No reason given)", player_names[pnum]), false); kickreason = KR_BAN; break; case KICK_MSG_CUSTOM_KICK: @@ -3032,7 +3023,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (pnum == consoleplayer) { - LUAh_GameQuit(false); + LUA_HookBool(false, HOOK(GameQuit)); #ifdef DUMPCONSISTENCY if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); #endif @@ -3452,7 +3443,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); if (!rejoined) - LUAh_PlayerJoin(newplayernum); + LUA_HookInt(newplayernum, HOOK(PlayerJoin)); } static boolean SV_AddWaitingPlayers(const char *name, const char *name2) @@ -3732,7 +3723,7 @@ static void HandleConnect(SINT8 node) static void HandleShutdown(SINT8 node) { (void)node; - LUAh_GameQuit(false); + LUA_HookBool(false, HOOK(GameQuit)); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -3747,7 +3738,7 @@ static void HandleShutdown(SINT8 node) static void HandleTimeout(SINT8 node) { (void)node; - LUAh_GameQuit(false); + LUA_HookBool(false, HOOK(GameQuit)); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -4268,7 +4259,7 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_RECEIVEDGAMESTATE: sendingsavegame[node] = false; resendingsavegame[node] = false; - savegameresendcooldown[node] = I_GetTime() + 15 * TICRATE; + savegameresendcooldown[node] = I_GetTime() + 5 * TICRATE; break; // -------------------------------------------- CLIENT RECEIVE ---------- case PT_SERVERTICS: diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 3d67525da..f3eb52423 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_event.h b/src/d_event.h index 3cce8fad1..1fd2e3824 100644 --- a/src/d_event.h +++ b/src/d_event.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_main.c b/src/d_main.c index 09f678ba6..0d0e2434a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,7 +15,7 @@ /// plus functions to parse command line parameters, configure game /// parameters, and call the startup functions. -#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) +#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) #include #include #endif @@ -175,10 +175,53 @@ void D_ProcessEvents(void) boolean eaten; + // Reset possibly stale mouse info + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); + mouse.buttons &= ~(MB_SCROLLUP|MB_SCROLLDOWN); + mouse2.buttons &= ~(MB_SCROLLUP|MB_SCROLLDOWN); + for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { + boolean hooked = false; + ev = &events[eventtail]; + // Set mouse buttons early in case event is eaten later + if (ev->type == ev_keydown || ev->type == ev_keyup) + { + // Mouse buttons + if ((UINT32)(ev->data1 - KEY_MOUSE1) < MOUSEBUTTONS) + { + if (ev->type == ev_keydown) + mouse.buttons |= 1 << (ev->data1 - KEY_MOUSE1); + else + mouse.buttons &= ~(1 << (ev->data1 - KEY_MOUSE1)); + } + else if ((UINT32)(ev->data1 - KEY_2MOUSE1) < MOUSEBUTTONS) + { + if (ev->type == ev_keydown) + mouse2.buttons |= 1 << (ev->data1 - KEY_2MOUSE1); + else + mouse2.buttons &= ~(1 << (ev->data1 - KEY_2MOUSE1)); + } + // Scroll (has no keyup event) + else switch (ev->data1) { + case KEY_MOUSEWHEELUP: + mouse.buttons |= MB_SCROLLUP; + break; + case KEY_MOUSEWHEELDOWN: + mouse.buttons |= MB_SCROLLDOWN; + break; + case KEY_2MOUSEWHEELUP: + mouse2.buttons |= MB_SCROLLUP; + break; + case KEY_2MOUSEWHEELDOWN: + mouse2.buttons |= MB_SCROLLDOWN; + break; + } + } + // Screenshots over everything so that they can be taken anywhere. if (M_ScreenshotResponder(ev)) continue; // ate the event @@ -189,6 +232,12 @@ void D_ProcessEvents(void) continue; } + if (!CON_Ready() && !menuactive) { + if (G_LuaResponder(ev)) + continue; + hooked = true; + } + // Menu input #ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); @@ -203,6 +252,12 @@ void D_ProcessEvents(void) if (eaten) continue; // menu ate the event + if (!hooked && !CON_Ready()) { + if (G_LuaResponder(ev)) + continue; + hooked = true; + } + // console input #ifdef HAVE_THREADS I_lock_mutex(&con_mutex); @@ -217,8 +272,16 @@ void D_ProcessEvents(void) if (eaten) continue; // ate the event + if (!hooked && G_LuaResponder(ev)) + continue; + G_Responder(ev); } + + if (mouse.rdx || mouse.rdy) + G_SetMouseDeltas(mouse.rdx, mouse.rdy, 1); + if (mouse2.rdx || mouse2.rdy) + G_SetMouseDeltas(mouse2.rdx, mouse2.rdy, 2); } // @@ -950,7 +1013,7 @@ static void IdentifyVersion(void) char *srb2wad; const char *srb2waddir = NULL; -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) // change to the directory where 'srb2.pk3' is found srb2waddir = I_LocateWad(); #endif @@ -1061,7 +1124,7 @@ void D_SRB2Main(void) // Print GPL notice for our console users (Linux) CONS_Printf( "\n\nSonic Robo Blast 2\n" - "Copyright (C) 1998-2020 by Sonic Team Junior\n\n" + "Copyright (C) 1998-2021 by Sonic Team Junior\n\n" "This program comes with ABSOLUTELY NO WARRANTY.\n\n" "This is free software, and you are welcome to redistribute it\n" "and/or modify it under the terms of the GNU General Public License\n" @@ -1123,7 +1186,7 @@ void D_SRB2Main(void) if (!userhome) { -#if ((defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)) && !defined (__CYGWIN__) +#if (defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)) && !defined (__CYGWIN__) I_Error("Please set $HOME to your home directory\n"); #else if (dedicated) @@ -1316,7 +1379,7 @@ void D_SRB2Main(void) G_LoadGameData(); -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen #endif @@ -1582,7 +1645,7 @@ const char *D_Home(void) userhome = M_GetNextParm(); else { -#if !((defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)) && !defined (__APPLE__) +#if !(defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)) if (FIL_FileOK(CONFIGFILENAME)) usehome = false; // Let's NOT use home else diff --git a/src/d_main.h b/src/d_main.h index 81de0634d..e282906d9 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -40,10 +40,6 @@ void D_SRB2Main(void); // Called by IO functions when input is detected. void D_PostEvent(const event_t *ev); -#if defined (PC_DOS) && !defined (DOXYGEN) -void D_PostEvent_end(void); // delimiter for locking memory -#endif - void D_ProcessEvents(void); const char *D_Home(void); diff --git a/src/d_net.c b/src/d_net.c index d534b1b08..9e5abe24a 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_net.h b/src/d_net.h index ea6b5d4d9..dbc6d8ba5 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c177e4a4a..ea0d9ca80 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -171,7 +171,7 @@ void SendWeaponPref(void); void SendWeaponPref2(void); static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}}; -#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) +#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) static CV_PossibleValue_t mouse2port_cons_t[] = {{0, "/dev/gpmdata"}, {1, "/dev/ttyS0"}, {2, "/dev/ttyS1"}, {3, "/dev/ttyS2"}, {4, "/dev/ttyS3"}, {0, NULL}}; #else @@ -258,7 +258,7 @@ consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_J consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save #endif -#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) +#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL); consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL); #else @@ -794,7 +794,7 @@ void D_RegisterClientCommands(void) // WARNING: the order is important when initialising mouse2 // we need the mouse2port CV_RegisterVar(&cv_mouse2port); -#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) +#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) CV_RegisterVar(&cv_mouse2opt); #endif CV_RegisterVar(&cv_controlperkey); @@ -1319,8 +1319,9 @@ static void SendNameAndColor(void) cv_skin.value = R_SkinAvailable(cv_skin.string); if ((cv_skin.value < 0) || !R_SkinUsable(consoleplayer, cv_skin.value)) { - CV_StealthSet(&cv_skin, DEFAULTSKIN); - cv_skin.value = 0; + INT32 defaultSkinNum = GetPlayerDefaultSkin(consoleplayer); + CV_StealthSet(&cv_skin, skins[defaultSkinNum].name); + cv_skin.value = defaultSkinNum; } // Finally write out the complete packet and send it off. @@ -1481,7 +1482,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer])) { boolean kick = false; - INT32 s; + UINT32 unlockShift = 0; + UINT32 i; // team colors if (G_GametypeHasTeams()) @@ -1497,12 +1499,29 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) kick = true; // availabilities - for (s = 0; s < MAXSKINS; s++) + for (i = 0; i < MAXUNLOCKABLES; i++) { - if (!skins[s].availability && (p->availabilities & (1 << s))) + if (unlockables[i].type != SECRET_SKIN) + { + continue; + } + + unlockShift++; + } + + // If they set an invalid bit to true, then likely a modified client + if (unlockShift < 32) // 32 is the max the data type allows + { + UINT32 illegalMask = UINT32_MAX; + + for (i = 0; i < unlockShift; i++) + { + illegalMask &= ~(1 << i); + } + + if ((p->availabilities & illegalMask) != 0) { kick = true; - break; } } @@ -2104,7 +2123,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) } mapnumber = M_MapNumber(mapname[3], mapname[4]); - LUAh_MapChange(mapnumber); + LUA_HookInt(mapnumber, HOOK(MapChange)); G_InitNew(ultimatemode, mapname, resetplayer, skipprecutscene, FLS); if (demoplayback && !timingdemo) @@ -2689,7 +2708,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } // Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh - if (!LUAh_TeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) + if (!LUA_HookTeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) return; //no status changes after hidetime @@ -2850,7 +2869,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. if (displayplayer != consoleplayer) // You're already viewing yourself. No big deal. - LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); + LUA_HookViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -3799,7 +3818,7 @@ static void Command_Playintro_f(void) */ FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void) { - LUAh_GameQuit(true); + LUA_HookBool(true, HOOK(GameQuit)); I_Quit(); } @@ -4461,7 +4480,7 @@ void Command_ExitGame_f(void) { INT32 i; - LUAh_GameQuit(false); + LUA_HookBool(false, HOOK(GameQuit)); D_QuitNetGame(); CL_Reset(); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index e7076cabf..cae32643e 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -45,7 +45,7 @@ extern consvar_t cv_joyscale2; // splitscreen with second mouse extern consvar_t cv_mouse2port; extern consvar_t cv_usemouse2; -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) +#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) extern consvar_t cv_mouse2opt; #endif diff --git a/src/d_netfil.c b/src/d_netfil.c index 4e93f6600..15f9f1ff5 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,7 +15,7 @@ #include -#if defined (_WIN32) || defined (__DJGPP__) +#ifdef _WIN32 #include #include #else @@ -30,10 +30,6 @@ #elif defined (_WIN32) #include #endif -#ifdef __DJGPP__ -#include -#include -#endif #include "doomdef.h" #include "doomstat.h" @@ -574,7 +570,7 @@ static void SV_PrepareSendLuaFileToNextNode(void) // Find a client to send the file to for (i = 1; i < MAXNETNODES; i++) - if (nodeingame[i] && luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting + if (luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting { // Tell the client we're about to send them the file netbuffer->packettype = PT_SENDINGLUAFILE; @@ -582,6 +578,7 @@ static void SV_PrepareSendLuaFileToNextNode(void) I_Error("Failed to send a PT_SENDINGLUAFILE packet\n"); // !!! Todo: Handle failure a bit better lol luafiletransfers->nodestatus[i] = LFTNS_ASKED; + luafiletransfers->nodetimeouts[i] = I_GetTime() + 30 * TICRATE; return; } @@ -600,7 +597,7 @@ void SV_PrepareSendLuaFile(void) // Set status to "waiting" for everyone for (i = 0; i < MAXNETNODES; i++) - luafiletransfers->nodestatus[i] = LFTNS_WAITING; + luafiletransfers->nodestatus[i] = (nodeingame[i] ? LFTNS_WAITING : LFTNS_NONE); if (FIL_ReadFileOK(luafiletransfers->realfilename)) { @@ -661,12 +658,14 @@ void RemoveAllLuaFileTransfers(void) void SV_AbortLuaFileTransfer(INT32 node) { - if (luafiletransfers - && (luafiletransfers->nodestatus[node] == LFTNS_ASKED - || luafiletransfers->nodestatus[node] == LFTNS_SENDING)) + if (luafiletransfers) { - luafiletransfers->nodestatus[node] = LFTNS_WAITING; - SV_PrepareSendLuaFileToNextNode(); + if (luafiletransfers->nodestatus[node] == LFTNS_ASKED + || luafiletransfers->nodestatus[node] == LFTNS_SENDING) + { + SV_PrepareSendLuaFileToNextNode(); + } + luafiletransfers->nodestatus[node] = LFTNS_NONE; } } @@ -940,6 +939,22 @@ void FileSendTicker(void) filetx_t *f; INT32 packetsent, ram, i, j; + // If someone is taking too long to download, kick them with a timeout + // to prevent blocking the rest of the server... + if (luafiletransfers) + { + for (i = 1; i < MAXNETNODES; i++) + { + luafiletransfernodestatus_t status = luafiletransfers->nodestatus[i]; + + if (status != LFTNS_NONE && status != LFTNS_WAITING && status != LFTNS_SENT + && I_GetTime() > luafiletransfers->nodetimeouts[i]) + { + Net_ConnectionTimeout(i); + } + } + } + if (!filestosend) // No file to send return; diff --git a/src/d_netfil.h b/src/d_netfil.h index 7cd6e06d3..70b721bf7 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -88,10 +88,11 @@ boolean PT_RequestFile(INT32 node); typedef enum { + LFTNS_NONE, // This node is not connected LFTNS_WAITING, // This node is waiting for the server to send the file - LFTNS_ASKED, // The server has told the node they're ready to send the file + LFTNS_ASKED, // The server has told the node they're ready to send the file LFTNS_SENDING, // The server is sending the file to this node - LFTNS_SENT // The node already has the file + LFTNS_SENT // The node already has the file } luafiletransfernodestatus_t; typedef struct luafiletransfer_s @@ -102,6 +103,7 @@ typedef struct luafiletransfer_s INT32 id; // Callback ID boolean ongoing; luafiletransfernodestatus_t nodestatus[MAXNETNODES]; + tic_t nodetimeouts[MAXNETNODES]; struct luafiletransfer_s *next; } luafiletransfer_t; diff --git a/src/d_player.h b/src/d_player.h index 2e7afed88..54ab34288 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_think.h b/src/d_think.h index 4bdac4627..c3f91edc4 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 2a5ef0981..182b30e6a 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,6 +21,8 @@ #pragma interface #endif +#define MAXPREDICTTICS 12 + // Button/action code definitions. typedef enum { @@ -63,6 +65,7 @@ typedef struct INT16 angleturn; // <<16 for angle delta - saved as 1 byte into demos INT16 aiming; // vertical aiming, see G_BuildTicCmd UINT16 buttons; + UINT8 latency; // Netgames: how many tics ago was this ticcmd generated from this player's end? } ATTRPACK ticcmd_t; #if defined(_MSC_VER) diff --git a/src/deh_lua.c b/src/deh_lua.c index e6a436421..fbeaae08c 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,10 +25,6 @@ #include "deh_lua.h" #include "deh_tables.h" -#ifdef MUSICSLOT_COMPATIBILITY -#include "deh_soc.h" // for get_mus -#endif - // freeslot takes a name (string only!) // and allocates it to the appropriate free slot. // Returns the slot number allocated for it or nil if failed. @@ -430,29 +426,6 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word); return 0; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (!mathlib && fastncmp("mus_",word,4)) { - p = word+4; - if ((i = get_mus(p, false)) == 0) - return 0; - lua_pushinteger(L, i); - return 1; - } - else if (mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS! - p = word+4; - if ((i = get_mus(p, false)) == 0) - return luaL_error(L, "music '%s' could not be found.\n", word); - lua_pushinteger(L, i); - return 1; - } - else if (mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) { - p = word+2; - if ((i = get_mus(p, false)) == 0) - return luaL_error(L, "music '%s' could not be found.\n", word); - lua_pushinteger(L, i); - return 1; - } -#endif else if (!mathlib && fastncmp("pw_",word,3)) { p = word+3; for (i = 0; i < NUMPOWERS; i++) diff --git a/src/deh_lua.h b/src/deh_lua.h index cd927b9fd..9df4028bd 100644 --- a/src/deh_lua.h +++ b/src/deh_lua.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_soc.c b/src/deh_soc.c index 5b12ea1b0..3a611f3ba 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -127,6 +127,33 @@ static float searchfvalue(const char *s) #endif // These are for clearing all of various things +void clear_emblems(void) +{ + INT32 i; + + for (i = 0; i < MAXEMBLEMS; ++i) + { + Z_Free(emblemlocations[i].stringVar); + emblemlocations[i].stringVar = NULL; + } + + memset(&emblemlocations, 0, sizeof(emblemlocations)); + numemblems = 0; +} + +void clear_unlockables(void) +{ + INT32 i; + + for (i = 0; i < MAXUNLOCKABLES; ++i) + { + Z_Free(unlockables[i].stringVar); + unlockables[i].stringVar = NULL; + } + + memset(&unlockables, 0, sizeof(unlockables)); +} + void clear_conditionsets(void) { UINT8 i; @@ -229,7 +256,10 @@ void readPlayer(MYFILE *f, INT32 num) SLOTFOUND - for (i = 0; i < MAXLINELEN-3; i++) + // A friendly neighborhood alias for brevity's sake +#define NOTE_SIZE sizeof(description[num].notes) + + for (i = 0; i < (INT32)(MAXLINELEN-NOTE_SIZE-3); i++) { if (s[i] == '=') { @@ -239,8 +269,9 @@ void readPlayer(MYFILE *f, INT32 num) } if (playertext) { - strcpy(description[num].notes, playertext); - strcat(description[num].notes, myhashfgets(playertext, sizeof (description[num].notes), f)); + strlcpy(description[num].notes, playertext, NOTE_SIZE); + strlcat(description[num].notes, + myhashfgets(playertext, NOTE_SIZE, f), NOTE_SIZE); } else strcpy(description[num].notes, ""); @@ -249,7 +280,7 @@ void readPlayer(MYFILE *f, INT32 num) // It works down here, though. { INT32 numline = 0; - for (i = 0; (size_t)i < sizeof(description[num].notes)-1; i++) + for (i = 0; (size_t)i < NOTE_SIZE-1; i++) { if (numline < 20 && description[num].notes[i] == '\n') numline++; @@ -260,6 +291,7 @@ void readPlayer(MYFILE *f, INT32 num) } description[num].notes[strlen(description[num].notes)-1] = '\0'; description[num].notes[i] = '\0'; +#undef NOTE_SIZE continue; } @@ -1140,8 +1172,10 @@ void readgametype(MYFILE *f, char *gtname) } if (descr) { - strcpy(gtdescription, descr); - strcat(gtdescription, myhashfgets(descr, sizeof (gtdescription), f)); + strlcpy(gtdescription, descr, sizeof (gtdescription)); + strlcat(gtdescription, + myhashfgets(descr, sizeof (gtdescription), f), + sizeof (gtdescription)); } else strcpy(gtdescription, ""); @@ -1574,19 +1608,8 @@ void readlevelheader(MYFILE *f, INT32 num) sizeof(mapheaderinfo[num-1]->musname), va("Level header %d: music", num)); } } -#ifdef MUSICSLOT_COMPATIBILITY else if (fastcmp(word, "MUSICSLOT")) - { - i = get_mus(word2, true); - if (i && i <= 1035) - snprintf(mapheaderinfo[num-1]->musname, 7, "%sM", G_BuildMapName(i)); - else if (i && i <= 1050) - strncpy(mapheaderinfo[num-1]->musname, compat_special_music_slots[i - 1036], 7); - else - mapheaderinfo[num-1]->musname[0] = 0; // becomes empty string - mapheaderinfo[num-1]->musname[6] = 0; - } -#endif + deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num); else if (fastcmp(word, "MUSICTRACK")) mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1); else if (fastcmp(word, "MUSICPOS")) @@ -1964,19 +1987,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7); cutscenes[num]->scene[scenenum].musswitch[6] = 0; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastcmp(word, "MUSICSLOT")) - { - i = get_mus(word2, true); - if (i && i <= 1035) - snprintf(cutscenes[num]->scene[scenenum].musswitch, 7, "%sM", G_BuildMapName(i)); - else if (i && i <= 1050) - strncpy(cutscenes[num]->scene[scenenum].musswitch, compat_special_music_slots[i - 1036], 7); - else - cutscenes[num]->scene[scenenum].musswitch[0] = 0; // becomes empty string - cutscenes[num]->scene[scenenum].musswitch[6] = 0; - } -#endif else if (fastcmp(word, "MUSICTRACK")) { cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK; @@ -2239,19 +2249,6 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) strncpy(textprompts[num]->page[pagenum].musswitch, word2, 7); textprompts[num]->page[pagenum].musswitch[6] = 0; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastcmp(word, "MUSICSLOT")) - { - i = get_mus(word2, true); - if (i && i <= 1035) - snprintf(textprompts[num]->page[pagenum].musswitch, 7, "%sM", G_BuildMapName(i)); - else if (i && i <= 1050) - strncpy(textprompts[num]->page[pagenum].musswitch, compat_special_music_slots[i - 1036], 7); - else - textprompts[num]->page[pagenum].musswitch[0] = 0; // becomes empty string - textprompts[num]->page[pagenum].musswitch[6] = 0; - } -#endif else if (fastcmp(word, "MUSICTRACK")) { textprompts[num]->page[pagenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK; @@ -2577,20 +2574,6 @@ void readmenu(MYFILE *f, INT32 num) menupres[num].musname[6] = 0; titlechanged = true; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastcmp(word, "MUSICSLOT")) - { - value = get_mus(word2, true); - if (value && value <= 1035) - snprintf(menupres[num].musname, 7, "%sM", G_BuildMapName(value)); - else if (value && value <= 1050) - strncpy(menupres[num].musname, compat_special_music_slots[value - 1036], 7); - else - menupres[num].musname[0] = 0; // becomes empty string - menupres[num].musname[6] = 0; - titlechanged = true; - } -#endif else if (fastcmp(word, "MUSICTRACK")) { menupres[num].mustrack = ((UINT16)value - 1); @@ -2839,26 +2822,31 @@ void readsound(MYFILE *f, INT32 num) if (s[0] == '\n') break; + // First remove trailing newline, if there is one + tmp = strchr(s, '\n'); + if (tmp) + *tmp = '\0'; + tmp = strchr(s, '#'); if (tmp) *tmp = '\0'; if (s == tmp) continue; // Skip comment lines, but don't break. - word = strtok(s, " "); - if (word) - strupr(word); + // Set / reset word + word = s; + + // Get the part before the " = " + tmp = strchr(s, '='); + if (tmp) + *(tmp-1) = '\0'; else break; + strupr(word); - word2 = strtok(NULL, " "); - if (word2) - value = atoi(word2); - else - { - deh_warning("No value for token %s", word); - continue; - } + // Now get the part after + word2 = tmp += 2; + value = atoi(word2); // used for numerical settings if (fastcmp(word, "SINGULAR")) { @@ -3017,7 +3005,12 @@ void reademblemdata(MYFILE *f, INT32 num) else if (fastcmp(word, "COLOR")) emblemlocations[num-1].color = get_number(word2); else if (fastcmp(word, "VAR")) + { + Z_Free(emblemlocations[num-1].stringVar); + emblemlocations[num-1].stringVar = Z_StrDup(word2); + emblemlocations[num-1].var = get_number(word2); + } else deh_warning("Emblem %d: unknown word '%s'", num, word); } @@ -3219,11 +3212,16 @@ void readunlockable(MYFILE *f, INT32 num) unlockables[num].type = SECRET_WARP; else if (fastcmp(word2, "SOUNDTEST")) unlockables[num].type = SECRET_SOUNDTEST; + else if (fastcmp(word2, "SKIN")) + unlockables[num].type = SECRET_SKIN; else unlockables[num].type = (INT16)i; } else if (fastcmp(word, "VAR")) { + Z_Free(unlockables[num].stringVar); + unlockables[num].stringVar = Z_StrDup(word2); + // Support using the actual map name, // i.e., Level AB, Level FZ, etc. @@ -4178,46 +4176,6 @@ sfxenum_t get_sfx(const char *word) return sfx_None; } -#ifdef MUSICSLOT_COMPATIBILITY -UINT16 get_mus(const char *word, UINT8 dehacked_mode) -{ // Returns the value of MUS_ enumerations - UINT16 i; - char lumptmp[4]; - - if (*word >= '0' && *word <= '9') - return atoi(word); - if (!word[2] && toupper(word[0]) >= 'A' && toupper(word[0]) <= 'Z') - return (UINT16)M_MapNumber(word[0], word[1]); - - if (fastncmp("MUS_",word,4)) - word += 4; // take off the MUS_ - else if (fastncmp("O_",word,2) || fastncmp("D_",word,2)) - word += 2; // take off the O_ or D_ - - strncpy(lumptmp, word, 4); - lumptmp[3] = 0; - if (fasticmp("MAP",lumptmp)) - { - word += 3; - if (toupper(word[0]) >= 'A' && toupper(word[0]) <= 'Z') - return (UINT16)M_MapNumber(word[0], word[1]); - else if ((i = atoi(word))) - return i; - - word -= 3; - if (dehacked_mode) - deh_warning("Couldn't find music named 'MUS_%s'",word); - return 0; - } - for (i = 0; compat_special_music_slots[i][0]; ++i) - if (fasticmp(word, compat_special_music_slots[i])) - return i + 1036; - if (dehacked_mode) - deh_warning("Couldn't find music named 'MUS_%s'",word); - return 0; -} -#endif - hudnum_t get_huditem(const char *word) { // Returns the value of HUD_ enumerations hudnum_t i; @@ -4448,13 +4406,6 @@ static fixed_t find_const(const char **rword) free(word); return r; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastncmp("MUS_",word,4) || fastncmp("O_",word,2)) { - r = get_mus(word, true); - free(word); - return r; - } -#endif else if (fastncmp("PW_",word,3)) { r = get_power(word); free(word); diff --git a/src/deh_soc.h b/src/deh_soc.h index 2bcb52e70..28e3c9512 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -43,7 +43,7 @@ #include "info.h" #include "dehacked.h" -#include "doomdef.h" // MUSICSLOT_COMPATIBILITY, HWRENDER +#include "doomdef.h" // HWRENDER // Crazy word-reading stuff /// \todo Put these in a seperate file or something. @@ -52,9 +52,6 @@ statenum_t get_state(const char *word); spritenum_t get_sprite(const char *word); playersprite_t get_sprite2(const char *word); sfxenum_t get_sfx(const char *word); -#ifdef MUSICSLOT_COMPATIBILITY -UINT16 get_mus(const char *word, UINT8 dehacked_mode); -#endif hudnum_t get_huditem(const char *word); menutype_t get_menutype(const char *word); //INT16 get_gametype(const char *word); @@ -84,6 +81,8 @@ void readskincolor(MYFILE *f, INT32 num); void readthing(MYFILE *f, INT32 num); void readfreeslots(MYFILE *f); void readPlayer(MYFILE *f, INT32 num); +void clear_emblems(void); +void clear_unlockables(void); void clear_levels(void); void clear_conditionsets(void); #endif diff --git a/src/deh_tables.c b/src/deh_tables.c index dd6d7d69f..677b23214 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -22,6 +22,9 @@ #include "v_video.h" // video flags (for lua) #include "i_sound.h" // musictype_t (for lua) #include "g_state.h" // gamestate_t (for lua) +#include "g_game.h" // Joystick axes (for lua) +#include "i_joy.h" +#include "g_input.h" // Game controls (for lua) #include "deh_tables.h" @@ -5455,6 +5458,76 @@ struct int_const_s const INT_CONST[] = { {"GS_DEDICATEDSERVER",GS_DEDICATEDSERVER}, {"GS_WAITINGPLAYERS",GS_WAITINGPLAYERS}, + // Joystick axes + {"JA_NONE",JA_NONE}, + {"JA_TURN",JA_TURN}, + {"JA_MOVE",JA_MOVE}, + {"JA_LOOK",JA_LOOK}, + {"JA_STRAFE",JA_STRAFE}, + {"JA_DIGITAL",JA_DIGITAL}, + {"JA_JUMP",JA_JUMP}, + {"JA_SPIN",JA_SPIN}, + {"JA_FIRE",JA_FIRE}, + {"JA_FIRENORMAL",JA_FIRENORMAL}, + {"JOYAXISRANGE",JOYAXISRANGE}, + + // Game controls + {"gc_null",gc_null}, + {"gc_forward",gc_forward}, + {"gc_backward",gc_backward}, + {"gc_strafeleft",gc_strafeleft}, + {"gc_straferight",gc_straferight}, + {"gc_turnleft",gc_turnleft}, + {"gc_turnright",gc_turnright}, + {"gc_weaponnext",gc_weaponnext}, + {"gc_weaponprev",gc_weaponprev}, + {"gc_wepslot1",gc_wepslot1}, + {"gc_wepslot2",gc_wepslot2}, + {"gc_wepslot3",gc_wepslot3}, + {"gc_wepslot4",gc_wepslot4}, + {"gc_wepslot5",gc_wepslot5}, + {"gc_wepslot6",gc_wepslot6}, + {"gc_wepslot7",gc_wepslot7}, + {"gc_wepslot8",gc_wepslot8}, + {"gc_wepslot9",gc_wepslot9}, + {"gc_wepslot10",gc_wepslot10}, + {"gc_fire",gc_fire}, + {"gc_firenormal",gc_firenormal}, + {"gc_tossflag",gc_tossflag}, + {"gc_spin",gc_spin}, + {"gc_camtoggle",gc_camtoggle}, + {"gc_camreset",gc_camreset}, + {"gc_lookup",gc_lookup}, + {"gc_lookdown",gc_lookdown}, + {"gc_centerview",gc_centerview}, + {"gc_mouseaiming",gc_mouseaiming}, + {"gc_talkkey",gc_talkkey}, + {"gc_teamkey",gc_teamkey}, + {"gc_scores",gc_scores}, + {"gc_jump",gc_jump}, + {"gc_console",gc_console}, + {"gc_pause",gc_pause}, + {"gc_systemmenu",gc_systemmenu}, + {"gc_screenshot",gc_screenshot}, + {"gc_recordgif",gc_recordgif}, + {"gc_viewpoint",gc_viewpoint}, + {"gc_custom1",gc_custom1}, + {"gc_custom2",gc_custom2}, + {"gc_custom3",gc_custom3}, + {"num_gamecontrols",num_gamecontrols}, + + // Mouse buttons + {"MB_BUTTON1",MB_BUTTON1}, + {"MB_BUTTON2",MB_BUTTON2}, + {"MB_BUTTON3",MB_BUTTON3}, + {"MB_BUTTON4",MB_BUTTON4}, + {"MB_BUTTON5",MB_BUTTON5}, + {"MB_BUTTON6",MB_BUTTON6}, + {"MB_BUTTON7",MB_BUTTON7}, + {"MB_BUTTON8",MB_BUTTON8}, + {"MB_SCROLLUP",MB_SCROLLUP}, + {"MB_SCROLLDOWN",MB_SCROLLDOWN}, + {NULL,0} }; diff --git a/src/deh_tables.h b/src/deh_tables.h index d094bcbad..1f265cc99 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/dehacked.c b/src/dehacked.c index c2ea28d27..da8c81c35 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -188,26 +188,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) dbg_line = -1; // start at -1 so the first line is 0. while (!myfeof(f)) { - char origpos[128]; - INT32 size = 0; - char *traverse; - myfgets(s, MAXLINELEN, f); memcpy(textline, s, MAXLINELEN); if (s[0] == '\n' || s[0] == '#') continue; - traverse = s; - - while (traverse[0] != '\n') - { - traverse++; - size++; - } - - strncpy(origpos, s, size); - origpos[size] = '\0'; - if (NULL != (word = strtok(s, " "))) { strupr(word); if (word[strlen(word)-1] == '\n') @@ -562,13 +547,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) } if (clearall || fastcmp(word2, "UNLOCKABLES")) - memset(&unlockables, 0, sizeof(unlockables)); + clear_unlockables(); if (clearall || fastcmp(word2, "EMBLEMS")) - { - memset(&emblemlocations, 0, sizeof(emblemlocations)); - numemblems = 0; - } + clear_emblems(); if (clearall || fastcmp(word2, "EXTRAEMBLEMS")) { diff --git a/src/dehacked.h b/src/dehacked.h index 1620314ca..1b200e246 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomdata.h b/src/doomdata.h index b3f7f5c4d..e317fec1b 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomdef.h b/src/doomdef.h index 52abc9597..11ca80538 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -100,7 +100,7 @@ #include #include -#if defined (_WIN32) || defined (__DJGPP__) +#ifdef _WIN32 #include #endif @@ -112,7 +112,7 @@ //#define PARANOIA // do some tests that never fail but maybe // turn this on by make etc.. DEBUGMODE = 1 or use the Debug profile in the VC++ projects //#endif -#if defined (_WIN32) || (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (macintosh) +#if defined (_WIN32) || defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (macintosh) #define LOGMESSAGES // write message in log.txt #endif @@ -415,7 +415,7 @@ enum { }; // Name of local directory for config files and savegames -#if (((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON)) && !defined (__CYGWIN__)) && !defined (__APPLE__) +#if (defined (__unix__) || defined (UNIXCOMMON)) && !defined (__CYGWIN__) && !defined (__APPLE__) #define DEFAULTDIR ".srb2" #else #define DEFAULTDIR "srb2" @@ -604,10 +604,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.) //#define REDSANALOG -/// Backwards compatibility with musicslots. -/// \note You should leave this enabled unless you're working with a future SRB2 version. -#define MUSICSLOT_COMPATIBILITY - /// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls. //#define PAPER_COLLISIONCORRECTION diff --git a/src/doomstat.h b/src/doomstat.h index 2d28b81af..32669b68b 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -337,9 +337,9 @@ typedef struct fixed_t gravity; ///< Map-wide gravity. // Title card. - char ltzzpatch[8]; ///< Zig zag patch. - char ltzztext[8]; ///< Zig zag text. - char ltactdiamond[8]; ///< Act diamond. + char ltzzpatch[9]; ///< Zig zag patch. + char ltzztext[9]; ///< Zig zag text. + char ltactdiamond[9]; ///< Act diamond. // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. @@ -496,7 +496,7 @@ extern UINT32 lastcustomtol; extern tic_t totalplaytime; -extern UINT8 stagefailed; +extern boolean stagefailed; // Emeralds stored as bits to throw savegame hackers off. extern UINT16 emeralds; diff --git a/src/doomtype.h b/src/doomtype.h index 950f50856..3a57d90e8 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -54,17 +54,6 @@ typedef long ssize_t; #define PDWORD_PTR PDWORD #endif #endif -#elif defined (__DJGPP__) -#define UINT8 unsigned char -#define SINT8 signed char - -#define UINT16 unsigned short int -#define INT16 signed short int - -#define INT32 signed long -#define UINT32 unsigned long -#define INT64 signed long long -#define UINT64 unsigned long long #else #define __STDC_LIMIT_MACROS #include @@ -108,7 +97,7 @@ typedef long ssize_t; #define strncasecmp strnicmp #define strcasecmp strcmpi #endif -#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) +#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) #undef stricmp #define stricmp(x,y) strcasecmp(x,y) #undef strnicmp @@ -136,7 +125,7 @@ char *strcasestr(const char *in, const char *what); #endif #endif //macintosh -#if defined (PC_DOS) || defined (_WIN32) || defined (__HAIKU__) +#if defined (_WIN32) || defined (__HAIKU__) #define HAVE_DOSSTR_FUNCS #endif @@ -367,6 +356,8 @@ typedef UINT32 tic_t; #define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24) #endif +#define TOSTR(x) #x + /* preprocessor dumb and needs second macro to expand input */ #define WSTRING2(s) L ## s #define WSTRING(s) WSTRING2 (s) diff --git a/src/endian.h b/src/endian.h index 24d8e35cd..e78204e72 100644 --- a/src/endian.h +++ b/src/endian.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_finale.c b/src/f_finale.c index fdcfad279..e8757c18a 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1063,7 +1063,7 @@ boolean F_IntroResponder(event_t *event) // CREDITS // ========= static const char *credits[] = { - "\1Sonic Robo Blast II", + "\1Sonic Robo Blast 2", "\1Credits", "", "\1Game Design", diff --git a/src/f_finale.h b/src/f_finale.h index b3abf1778..4aa2c3f05 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_wipe.c b/src/f_wipe.c index 6afb8a6a7..7526aeca3 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_demo.c b/src/g_demo.c index 593fd7723..701f930e5 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -109,6 +109,7 @@ demoghost *ghosts = NULL; #define ZT_ANGLE 0x04 #define ZT_BUTTONS 0x08 #define ZT_AIMING 0x10 +#define ZT_LATENCY 0x20 #define DEMOMARKER 0x80 // demoend #define METALDEATH 0x44 #define METALSNICE 0x69 @@ -181,6 +182,8 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) oldcmd.buttons = (oldcmd.buttons & (BT_CAMLEFT|BT_CAMRIGHT)) | (READUINT16(demo_p) & ~(BT_CAMLEFT|BT_CAMRIGHT)); if (ziptic & ZT_AIMING) oldcmd.aiming = READINT16(demo_p); + if (ziptic & ZT_LATENCY) + oldcmd.latency = READUINT8(demo_p); G_CopyTiccmd(cmd, &oldcmd, 1); players[playernum].angleturn = cmd->angleturn; @@ -238,6 +241,13 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) ziptic |= ZT_AIMING; } + if (cmd->latency != oldcmd.latency) + { + WRITEUINT8(demo_p,cmd->latency); + oldcmd.latency = cmd->latency; + ziptic |= ZT_LATENCY; + } + *ziptic_p = ziptic; // attention here for the ticcmd size! @@ -679,6 +689,8 @@ void G_GhostTicker(void) g->p += 2; if (ziptic & ZT_AIMING) g->p += 2; + if (ziptic & ZT_LATENCY) + g->p++; // Grab ghost data. ziptic = READUINT8(g->p); @@ -1956,7 +1968,7 @@ void G_DoPlayDemo(char *defdemoname) // Set skin SetPlayerSkin(0, skin); - LUAh_MapChange(gamemap); + LUA_HookInt(gamemap, HOOK(MapChange)); displayplayer = consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); playeringame[0] = true; diff --git a/src/g_demo.h b/src/g_demo.h index df25042c4..73cf27358 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_game.c b/src/g_game.c index 2b304b4fd..13fdab877 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -169,7 +169,7 @@ static boolean exitgame = false; static boolean retrying = false; static boolean retryingmodeattack = false; -UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage. +boolean stagefailed = false; // Used for GEMS BONUS? Also to see if you beat the stage. UINT16 emeralds; INT32 luabanks[NUM_LUABANKS]; @@ -406,22 +406,6 @@ consvar_t cv_cam_lockonboss[2] = { CVAR_INIT ("cam2_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL), }; -typedef enum -{ - AXISNONE = 0, - AXISTURN, - AXISMOVE, - AXISLOOK, - AXISSTRAFE, - - AXISDIGITAL, // axes below this use digital deadzone - - AXISJUMP, - AXISSPIN, - AXISFIRE, - AXISFIRENORMAL, -} axis_input_e; - consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); @@ -841,7 +825,7 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming) return (INT16)((*aiming)>>16); } -static INT32 JoyAxis(axis_input_e axissel) +INT32 JoyAxis(joyaxis_e axissel) { INT32 retaxis; INT32 axisval; @@ -850,28 +834,28 @@ static INT32 JoyAxis(axis_input_e axissel) //find what axis to get switch (axissel) { - case AXISTURN: + case JA_TURN: axisval = cv_turnaxis.value; break; - case AXISMOVE: + case JA_MOVE: axisval = cv_moveaxis.value; break; - case AXISLOOK: + case JA_LOOK: axisval = cv_lookaxis.value; break; - case AXISSTRAFE: + case JA_STRAFE: axisval = cv_sideaxis.value; break; - case AXISJUMP: + case JA_JUMP: axisval = cv_jumpaxis.value; break; - case AXISSPIN: + case JA_SPIN: axisval = cv_spinaxis.value; break; - case AXISFIRE: + case JA_FIRE: axisval = cv_fireaxis.value; break; - case AXISFIRENORMAL: + case JA_FIRENORMAL: axisval = cv_firenaxis.value; break; default: @@ -903,7 +887,7 @@ static INT32 JoyAxis(axis_input_e axissel) if (retaxis > (+JOYAXISRANGE)) retaxis = +JOYAXISRANGE; - if (!Joystick.bGamepadStyle && axissel > AXISDIGITAL) + if (!Joystick.bGamepadStyle && axissel >= JA_DIGITAL) { const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) @@ -914,7 +898,7 @@ static INT32 JoyAxis(axis_input_e axissel) return retaxis; } -static INT32 Joy2Axis(axis_input_e axissel) +INT32 Joy2Axis(joyaxis_e axissel) { INT32 retaxis; INT32 axisval; @@ -923,28 +907,28 @@ static INT32 Joy2Axis(axis_input_e axissel) //find what axis to get switch (axissel) { - case AXISTURN: + case JA_TURN: axisval = cv_turnaxis2.value; break; - case AXISMOVE: + case JA_MOVE: axisval = cv_moveaxis2.value; break; - case AXISLOOK: + case JA_LOOK: axisval = cv_lookaxis2.value; break; - case AXISSTRAFE: + case JA_STRAFE: axisval = cv_sideaxis2.value; break; - case AXISJUMP: + case JA_JUMP: axisval = cv_jumpaxis2.value; break; - case AXISSPIN: + case JA_SPIN: axisval = cv_spinaxis2.value; break; - case AXISFIRE: + case JA_FIRE: axisval = cv_fireaxis2.value; break; - case AXISFIRENORMAL: + case JA_FIRENORMAL: axisval = cv_firenaxis2.value; break; default: @@ -978,7 +962,7 @@ static INT32 Joy2Axis(axis_input_e axissel) if (retaxis > (+JOYAXISRANGE)) retaxis = +JOYAXISRANGE; - if (!Joystick2.bGamepadStyle && axissel > AXISDIGITAL) + if (!Joystick2.bGamepadStyle && axissel >= JA_DIGITAL) { const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone2.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) @@ -1094,7 +1078,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0; INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, turnmultiplier, mousemove; controlstyle_e controlstyle = G_ControlStyle(ssplayer); - INT32 *mx; INT32 *my; INT32 *mly; + INT32 mdx, mdy, mldy; static INT32 turnheld[2]; // for accelerative turning static boolean keyboard_look[2]; // true if lookup/down using keyboard @@ -1117,9 +1101,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) invertmouse = cv_invertmouse.value; turnmultiplier = cv_cam_turnmultiplier.value; mousemove = cv_mousemove.value; - mx = &mousex; - my = &mousey; - mly = &mlooky; + mdx = mouse.dx; + mdy = -mouse.dy; + mldy = -mouse.mlookdy; G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver } else @@ -1131,12 +1115,15 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) invertmouse = cv_invertmouse2.value; turnmultiplier = cv_cam2_turnmultiplier.value; mousemove = cv_mousemove2.value; - mx = &mouse2x; - my = &mouse2y; - mly = &mlook2y; + mdx = mouse2.dx; + mdy = -mouse2.dy; + mldy = -mouse2.mlookdy; G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver } + if (menuactive || CON_Ready() || chat_on) + mdx = mdy = mldy = 0; + strafeisturn = controlstyle == CS_SIMPLE && ticcmd_centerviewdown[forplayer] && ((cv_cam_lockedinput[forplayer].value && !ticcmd_ztargetfocus[forplayer]) || (player->pflags & PF_STARTDASH)) && !player->climbing && player->powers[pw_carry] != CR_MINECART; @@ -1179,10 +1166,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) *myaiming = 0; joyaiming[forplayer] = thisjoyaiming; - turnaxis = PlayerJoyAxis(ssplayer, AXISTURN); + turnaxis = PlayerJoyAxis(ssplayer, JA_TURN); if (strafeisturn) - turnaxis += PlayerJoyAxis(ssplayer, AXISSTRAFE); - lookaxis = PlayerJoyAxis(ssplayer, AXISLOOK); + turnaxis += PlayerJoyAxis(ssplayer, JA_STRAFE); + lookaxis = PlayerJoyAxis(ssplayer, JA_LOOK); lookjoystickvector.xaxis = turnaxis; lookjoystickvector.yaxis = lookaxis; G_HandleAxisDeadZone(forplayer, &lookjoystickvector); @@ -1261,8 +1248,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) tta_factor[forplayer] = 0; // suspend turn to angle } - strafeaxis = strafeisturn ? 0 : PlayerJoyAxis(ssplayer, AXISSTRAFE); - moveaxis = PlayerJoyAxis(ssplayer, AXISMOVE); + strafeaxis = strafeisturn ? 0 : PlayerJoyAxis(ssplayer, JA_STRAFE); + moveaxis = PlayerJoyAxis(ssplayer, JA_MOVE); movejoystickvector.xaxis = strafeaxis; movejoystickvector.yaxis = moveaxis; G_HandleAxisDeadZone(forplayer, &movejoystickvector); @@ -1318,12 +1305,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } // fire with any button/key - axis = PlayerJoyAxis(ssplayer, AXISFIRE); + axis = PlayerJoyAxis(ssplayer, JA_FIRE); if (PLAYERINPUTDOWN(ssplayer, gc_fire) || (usejoystick && axis > 0)) cmd->buttons |= BT_ATTACK; // fire normal with any button/key - axis = PlayerJoyAxis(ssplayer, AXISFIRENORMAL); + axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL); if (PLAYERINPUTDOWN(ssplayer, gc_firenormal) || (usejoystick && axis > 0)) cmd->buttons |= BT_FIRENORMAL; @@ -1339,7 +1326,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->buttons |= BT_CUSTOM3; // use with any button/key - axis = PlayerJoyAxis(ssplayer, AXISSPIN); + axis = PlayerJoyAxis(ssplayer, JA_SPIN); if (PLAYERINPUTDOWN(ssplayer, gc_spin) || (usejoystick && axis > 0)) cmd->buttons |= BT_SPIN; @@ -1457,7 +1444,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // jump button - axis = PlayerJoyAxis(ssplayer, AXISJUMP); + axis = PlayerJoyAxis(ssplayer, JA_JUMP); if (PLAYERINPUTDOWN(ssplayer, gc_jump) || (usejoystick && axis > 0)) cmd->buttons |= BT_JUMP; @@ -1476,7 +1463,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) keyboard_look[forplayer] = false; // looking up/down - *myaiming += (*mly<<19)*player_invert*screen_invert; + *myaiming += (mldy<<19)*player_invert*screen_invert; } if (analogjoystickmove && joyaiming[forplayer] && lookjoystickvector.yaxis != 0 && configlookaxis != 0) @@ -1510,24 +1497,22 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } if (!mouseaiming && mousemove) - forward += *my; + forward += mdy; if ((!demoplayback && (player->pflags & PF_SLIDING))) // Analog for mouse - side += *mx*2; + side += mdx*2; else if (controlstyle == CS_LMAOGALOG) { - if (*mx) + if (mdx) { - if (*mx > 0) + if (mdx > 0) cmd->buttons |= BT_CAMRIGHT; else cmd->buttons |= BT_CAMLEFT; } } else - cmd->angleturn = (INT16)(cmd->angleturn - (*mx*8)); - - *mx = *my = *mly = 0; + cmd->angleturn = (INT16)(cmd->angleturn - (mdx*8)); if (forward > MAXPLMOVE) forward = MAXPLMOVE; @@ -1687,12 +1672,16 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->angleturn = orighookangle; - LUAh_PlayerCmd(player, cmd); + LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd)); extra = cmd->angleturn - orighookangle; cmd->angleturn = origangle + extra; *myangle += extra << 16; *myaiming += (cmd->aiming - origaiming) << 16; + + // Send leveltime when this tic was generated to the server for control lag calculations. + // Only do this when in a level. Also do this after the hook, so that it can't overwrite this. + cmd->latency = (leveltime & 0xFF); } //Reset away view if a command is given. @@ -1701,7 +1690,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -1724,6 +1713,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) dest[i].angleturn = SHORT(src[i].angleturn); dest[i].aiming = (INT16)SHORT(src[i].aiming); dest[i].buttons = (UINT16)SHORT(src[i].buttons); + dest[i].latency = src[i].latency; } return dest; } @@ -1873,8 +1863,8 @@ void G_DoLoadLevel(boolean resetplayer) joyxmove[i] = joyymove[i] = 0; joy2xmove[i] = joy2ymove[i] = 0; } - mousex = mousey = 0; - mouse2x = mouse2y = 0; + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); @@ -2074,7 +2064,7 @@ boolean G_Responder(event_t *ev) continue; // Call ViewpointSwitch hooks here. - canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); + canSwitchView = LUA_HookViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); if (canSwitchView == 1) // Set viewpoint to this player break; else if (canSwitchView == 2) // Skip this player @@ -2198,6 +2188,16 @@ boolean G_Responder(event_t *ev) return false; } +// +// G_LuaResponder +// Let Lua handle key events. +// +boolean G_LuaResponder(event_t *ev) +{ + return (ev->type == ev_keydown && LUA_HookKey(ev->data1, HOOK(KeyDown))) || + (ev->type == ev_keyup && LUA_HookKey(ev->data1, HOOK(KeyUp))); +} + // // G_Ticker // Make ticcmd_ts for the players. @@ -2306,6 +2306,9 @@ void G_Ticker(boolean run) players[i].cmd.angleturn &= ~TICCMD_RECEIVED; players[i].cmd.angleturn |= received; + + // Use the leveltime sent in the player's ticcmd to determine control lag + players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1); } } @@ -2745,7 +2748,7 @@ void G_SpawnPlayer(INT32 playernum) P_SpawnPlayer(playernum); G_MovePlayerToSpawnOrStarpost(playernum); - LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) + LUA_HookPlayer(&players[playernum], HOOK(PlayerSpawn)); // Lua hook for player spawning :) } void G_MovePlayerToSpawnOrStarpost(INT32 playernum) @@ -3095,8 +3098,8 @@ void G_DoReborn(INT32 playernum) joyxmove[i] = joyymove[i] = 0; joy2xmove[i] = joy2ymove[i] = 0; } - mousex = mousey = 0; - mouse2x = mouse2y = 0; + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); @@ -3124,7 +3127,7 @@ void G_DoReborn(INT32 playernum) } else { - LUAh_MapChange(gamemap); + LUA_HookInt(gamemap, HOOK(MapChange)); titlecardforreload = true; G_DoLoadLevel(true); titlecardforreload = false; @@ -3507,6 +3510,7 @@ tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = { {"MARIO",TOL_MARIO}, {"NIGHTS",TOL_NIGHTS}, {"OLDBRAK",TOL_ERZ3}, + {"ERZ3",TOL_ERZ3}, {"XMAS",TOL_XMAS}, {"CHRISTMAS",TOL_XMAS}, @@ -3742,7 +3746,7 @@ static void G_UpdateVisited(void) // Update visitation flags? if ((!modifiedgame || savemoddata) // Not modified && !multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode - && !(spec && stagefailed)) // Not failed the special stage + && !stagefailed) // Did not fail the stage { UINT8 earnedEmblems; @@ -3927,12 +3931,13 @@ static void G_DoCompleted(void) { token--; - for (i = 0; i < 7; i++) - if (!(emeralds & (1<cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum + && !modeattacking + && skipstats <= 1 + && (gamecomplete || !(marathonmode & MA_NOCUTSCENES)) + && stagefailed == false) + { + // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); + } else { if (nextmap < 1100-1) @@ -4617,6 +4630,9 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) UINT8 *end_p = savebuffer + length; UINT8 *lives_p; SINT8 pllives; +#ifdef NEWSKINSAVES + INT16 backwardsCompat = 0; +#endif save_p = savebuffer; // Version check @@ -4635,9 +4651,23 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) // P_UnArchivePlayer() CHECKPOS - (void)READUINT16(save_p); +#ifdef NEWSKINSAVES + backwardsCompat = READUINT16(save_p); CHECKPOS + if (backwardsCompat == NEWSKINSAVES) // New save, read skin names +#endif + { + char ourSkinName[SKINNAMESIZE+1]; + char botSkinName[SKINNAMESIZE+1]; + + READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); + CHECKPOS + + READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + CHECKPOS + } + WRITEUINT8(save_p, numgameovers); CHECKPOS diff --git a/src/g_game.h b/src/g_game.h index 744d6755a..f98269fce 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -85,6 +85,25 @@ typedef enum } lockassist_e; +typedef enum +{ + JA_NONE = 0, + JA_TURN, + JA_MOVE, + JA_LOOK, + JA_STRAFE, + + JA_DIGITAL, // axes henceforth use digital deadzone + + JA_JUMP = JA_DIGITAL, + JA_SPIN, + JA_FIRE, + JA_FIRENORMAL, +} joyaxis_e; + +INT32 JoyAxis(joyaxis_e axissel); +INT32 Joy2Axis(joyaxis_e axissel); + // mouseaiming (looking up/down with the mouse or keyboard) #define KB_LOOKSPEED (1<<25) #define MAXPLMOVE (50) @@ -204,6 +223,7 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); +boolean G_LuaResponder(event_t *ev); void G_AddPlayer(INT32 playernum); diff --git a/src/g_input.c b/src/g_input.c index d3c21e774..2f7980c64 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -31,10 +31,8 @@ consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL); consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL); -INT32 mousex, mousey; -INT32 mlooky; // like mousey but with a custom sensitivity for mlook - -INT32 mouse2x, mouse2y, mlook2y; +mouse_t mouse; +mouse_t mouse2; // joystick values are repeated INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET]; @@ -140,11 +138,8 @@ void G_MapEventsToControls(event_t *ev) break; case ev_mouse: // buttons are virtual keys - if (menuactive || CON_Ready() || chat_on) - break; - mousex = (INT32)(ev->data2*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f)); - mousey = (INT32)(ev->data3*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f)); - mlooky = (INT32)(ev->data3*((cv_mouseysens.value*cv_mousesens.value)/110.0f + 0.1f)); + mouse.rdx = ev->data2; + mouse.rdy = ev->data3; break; case ev_joystick: // buttons are virtual keys @@ -166,9 +161,8 @@ void G_MapEventsToControls(event_t *ev) case ev_mouse2: // buttons are virtual keys if (menuactive || CON_Ready() || chat_on) break; - mouse2x = (INT32)(ev->data2*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); - mouse2y = (INT32)(ev->data3*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); - mlook2y = (INT32)(ev->data3*((cv_mouseysens2.value*cv_mousesens2.value)/110.0f + 0.1f)); + mouse2.rdx = ev->data2; + mouse2.rdy = ev->data3; break; default: @@ -630,7 +624,7 @@ void G_ClearAllControlKeys(void) // Returns the name of a key (or virtual key for mouse and joy) // the input value being an keynum // -const char *G_KeynumToString(INT32 keynum) +const char *G_KeyNumToString(INT32 keynum) { static char keynamestr[8]; @@ -654,7 +648,7 @@ const char *G_KeynumToString(INT32 keynum) return keynamestr; } -INT32 G_KeyStringtoNum(const char *keystr) +INT32 G_KeyStringToNum(const char *keystr) { UINT32 j; @@ -817,10 +811,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(fromcontrols[i][0])); + G_KeyNumToString(fromcontrols[i][0])); if (fromcontrols[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrols[i][1])); + fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrols[i][1])); else fprintf(f, "\n"); } @@ -828,10 +822,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(fromcontrolsbis[i][0])); + G_KeyNumToString(fromcontrolsbis[i][0])); if (fromcontrolsbis[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsbis[i][1])); + fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrolsbis[i][1])); else fprintf(f, "\n"); } @@ -1007,8 +1001,8 @@ static void setcontrol(INT32 (*gc)[2]) CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl); return; } - keynum1 = G_KeyStringtoNum(COM_Argv(2)); - keynum2 = G_KeyStringtoNum(COM_Argv(3)); + keynum1 = G_KeyStringToNum(COM_Argv(2)); + keynum2 = G_KeyStringToNum(COM_Argv(3)); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) @@ -1073,3 +1067,17 @@ void Command_Setcontrol2_f(void) setcontrol(gamecontrolbis); } + +void G_SetMouseDeltas(INT32 dx, INT32 dy, UINT8 ssplayer) +{ + mouse_t *m = ssplayer == 1 ? &mouse : &mouse2; + consvar_t *cvsens, *cvysens; + + cvsens = ssplayer == 1 ? &cv_mousesens : &cv_mousesens2; + cvysens = ssplayer == 1 ? &cv_mouseysens : &cv_mouseysens2; + m->rdx = dx; + m->rdy = dy; + m->dx = (INT32)(m->rdx*((cvsens->value*cvsens->value)/110.0f + 0.1f)); + m->dy = (INT32)(m->rdy*((cvsens->value*cvsens->value)/110.0f + 0.1f)); + m->mlookdy = (INT32)(m->rdy*((cvysens->value*cvsens->value)/110.0f + 0.1f)); +} diff --git a/src/g_input.h b/src/g_input.h index ce38f6ba9..ffd0cb560 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -116,9 +116,29 @@ extern consvar_t cv_mousesens, cv_mouseysens; extern consvar_t cv_mousesens2, cv_mouseysens2; extern consvar_t cv_controlperkey; -extern INT32 mousex, mousey; -extern INT32 mlooky; //mousey with mlookSensitivity -extern INT32 mouse2x, mouse2y, mlook2y; +typedef struct +{ + INT32 dx; // deltas with mousemove sensitivity + INT32 dy; + INT32 mlookdy; // dy with mouselook sensitivity + INT32 rdx; // deltas without sensitivity + INT32 rdy; + UINT16 buttons; +} mouse_t; + +#define MB_BUTTON1 0x0001 +#define MB_BUTTON2 0x0002 +#define MB_BUTTON3 0x0004 +#define MB_BUTTON4 0x0008 +#define MB_BUTTON5 0x0010 +#define MB_BUTTON6 0x0020 +#define MB_BUTTON7 0x0040 +#define MB_BUTTON8 0x0080 +#define MB_SCROLLUP 0x0100 +#define MB_SCROLLDOWN 0x0200 + +extern mouse_t mouse; +extern mouse_t mouse2; extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET]; @@ -161,8 +181,8 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin]; void G_MapEventsToControls(event_t *ev); // returns the name of a key -const char *G_KeynumToString(INT32 keynum); -INT32 G_KeyStringtoNum(const char *keystr); +const char *G_KeyNumToString(INT32 keynum); +INT32 G_KeyStringToNum(const char *keystr); // detach any keys associated to the given game control void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control); @@ -175,4 +195,7 @@ void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const I void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]); INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify); +// sets the members of a mouse_t given position deltas +void G_SetMouseDeltas(INT32 dx, INT32 dy, UINT8 ssplayer); + #endif diff --git a/src/g_state.h b/src/g_state.h index e364c5a35..589dc6361 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/CMakeLists.txt b/src/hardware/CMakeLists.txt new file mode 100644 index 000000000..4e9c67d2f --- /dev/null +++ b/src/hardware/CMakeLists.txt @@ -0,0 +1 @@ +target_sourcefile(c) diff --git a/src/hardware/Sourcefile b/src/hardware/Sourcefile new file mode 100644 index 000000000..1c05de76c --- /dev/null +++ b/src/hardware/Sourcefile @@ -0,0 +1,13 @@ +hw_bsp.c +hw_draw.c +hw_light.c +hw_main.c +hw_clip.c +hw_md2.c +hw_cache.c +hw_md2load.c +hw_md3load.c +hw_model.c +u_list.c +hw_batching.c +r_opengl/r_opengl.c diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index fb3417158..0ac33d136 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -137,6 +137,8 @@ static int comparePolygons(const void *p1, const void *p2) PolygonArrayEntry* poly2 = &polygonArray[index2]; int diff; INT64 diff64; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; int shader1 = poly1->shader; int shader2 = poly2->shader; @@ -152,7 +154,11 @@ static int comparePolygons(const void *p1, const void *p2) if (shader1 == -1 && shader2 == -1) return index1 - index2; - diff64 = poly1->texture - poly2->texture; + if (poly1->texture) + downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons + if (poly2->texture) + downloaded2 = poly2->texture->downloaded; + diff64 = downloaded1 - downloaded2; if (diff64 != 0) return diff64; diff = poly1->polyFlags - poly2->polyFlags; @@ -184,16 +190,21 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2) GLMipmap_t *texture1 = poly1->texture; GLMipmap_t *texture2 = poly2->texture; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) texture1 = NULL; if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) texture2 = NULL; - diff64 = texture1 - texture2; - if (diff64 != 0) return diff64; - + if (texture1) + downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons + if (texture2) + downloaded2 = texture2->downloaded; // skywalls and horizon lines must retain their order for horizon lines to work - if (texture1 == NULL && texture2 == NULL) + if (!texture1 && !texture2) return index1 - index2; + diff64 = downloaded1 - downloaded2; + if (diff64 != 0) return diff64; diff = poly1->polyFlags - poly2->polyFlags; if (diff != 0) return diff; diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index 42291a0df..9ccc7de3d 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 83a4e2e03..317efd320 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index 7e56a14d0..5aba6a2a9 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index bd6afc74f..8df9b8916 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -216,28 +216,28 @@ enum EPolyFlags PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pixels are discarded (holes in texture) PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency PF_Environment = 0x00000004, // Poly should be drawn environment mapped. (Hurdler: used for text drawing) - PF_Additive = 0x00000008, // Additive color blending - PF_AdditiveSource = 0x00000010, // Source blending factor is additive. This is the opposite of regular additive blending. - PF_Subtractive = 0x00000020, // Subtractive color blending - PF_ReverseSubtract = 0x00000040, // Reverse subtract, used in wall splats (decals) - PF_Multiplicative = 0x00000080, // Multiplicative color blending + PF_Additive = 0x00000008, // Source blending factor is additive. + PF_Subtractive = 0x00000010, // Subtractive color blending + PF_ReverseSubtract = 0x00000020, // Reverse subtract, used in wall splats (decals) + PF_Multiplicative = 0x00000040, // Multiplicative color blending PF_Fog = 0x20000000, // Fog blocks PF_NoAlphaTest = 0x40000000, // Disables alpha testing - PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest, + PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest, // other flag bits PF_Occlude = 0x00000100, // Updates the depth buffer PF_NoDepthTest = 0x00000200, // Disables the depth test mode PF_Invisible = 0x00000400, // Disables write to color buffer PF_Decal = 0x00000800, // Enables polygon offset - PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB) + PF_Modulated = 0x00001000, // Modulation (multiply output with constant RGBA) // When set, pass the color constant into the FSurfaceInfo -> PolyColor PF_NoTexture = 0x00002000, // Disables texturing PF_Corona = 0x00004000, // Tells the renderer we are drawing a corona - PF_Ripple = 0x00008000, // Water effect shader + PF_ColorMapped = 0x00008000, // Surface has "tint" and "fade" colors, which are sent as uniforms to a shader. PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y PF_ForceWrapX = 0x00020000, // Forces repeat texture on X - PF_ForceWrapY = 0x00040000 // Forces repeat texture on Y + PF_ForceWrapY = 0x00040000, // Forces repeat texture on Y + PF_Ripple = 0x00100000 // Water ripple effect. The current backend doesn't use it for anything. }; @@ -266,7 +266,6 @@ struct FTextureInfo }; typedef struct FTextureInfo FTextureInfo; -// jimita 14032019 struct FLightInfo { FUINT light_level; @@ -282,7 +281,7 @@ struct FSurfaceInfo RGBA_t PolyColor; RGBA_t TintColor; RGBA_t FadeColor; - FLightInfo LightInfo; // jimita 14032019 + FLightInfo LightInfo; }; typedef struct FSurfaceInfo FSurfaceInfo; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 8c92c6709..e83aff0d7 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -437,18 +437,9 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (!(option & V_SCALEPATCHMASK)) { - // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) - // cx and cy are possibly *slightly* off from float maths - // This is done before here compared to software because we directly alter cx and cy to centre - if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT) - { - const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0])); - if (!column->topdelta) - { - const UINT8 *source = (const UINT8 *)(column) + 3; - HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } - } + // if it's meant to cover the whole screen, black out the rest + // no the patch is cropped do not do this ever + // centre screen if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) { @@ -470,11 +461,11 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fwidth = w; fheight = h; - if (fwidth > gpatch->width) - fwidth = gpatch->width; + if (sx + w > gpatch->width) + fwidth = gpatch->width - sx; - if (fheight > gpatch->height) - fheight = gpatch->height; + if (sy + h > gpatch->height) + fheight = gpatch->height - sy; if (pscale != FRACUNIT) { @@ -506,13 +497,13 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, v[0].s = v[3].s = ((sx)/(float)(gpatch->width))*hwrPatch->max_s; if (sx + w > gpatch->width) - v[2].s = v[1].s = hwrPatch->max_s - ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s; + v[2].s = v[1].s = hwrPatch->max_s; else v[2].s = v[1].s = ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s; v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t; if (sy + h > gpatch->height) - v[2].t = v[3].t = hwrPatch->max_t - ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t; + v[2].t = v[3].t = hwrPatch->max_t; else v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t; diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index da4ee8614..d4a586d41 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -68,7 +68,6 @@ EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); #define SCREENVERTS 10 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); -// jimita EXPORT boolean HWRAPI(CompileShaders) (void); EXPORT void HWRAPI(CleanShaders) (void); EXPORT void HWRAPI(SetShader) (int type); diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 2aba62248..37d77b467 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 93c61f4e7..e83d9a6ec 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,7 +35,7 @@ #define DL_HIGH_QUALITY //#define STATICLIGHT //Hurdler: TODO! -#define LIGHTMAPFLAGS (PF_Modulated|PF_AdditiveSource) +#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive) #ifdef ALAM_LIGHTING static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode @@ -1056,7 +1056,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr) HWR_GetPic(coronalumpnum); /// \todo use different coronas - HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_Corona | PF_NoDepthTest); + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Corona | PF_NoDepthTest); } } #endif @@ -1144,7 +1144,7 @@ void HWR_DrawCoronas(void) light[3].y = cy+size*1.33f; light[3].s = 0.0f; light[3].t = 1.0f; - HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_NoDepthTest | PF_Corona); + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_NoDepthTest | PF_Corona); } } #endif diff --git a/src/hardware/hw_light.h b/src/hardware/hw_light.h index fed7db47f..244cc921f 100644 --- a/src/hardware/hw_light.h +++ b/src/hardware/hw_light.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8bbe78f00..e0851af85 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -173,6 +173,11 @@ boolean gl_shadersavailable = true; // Lighting // ========================================================================== +static boolean HWR_UseShader(void) +{ + return (cv_glshaders.value && gl_shadersavailable); +} + void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap) { RGBA_t poly_color, tint_color, fade_color; @@ -182,7 +187,7 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col fade_color.rgba = (colormap != NULL) ? (UINT32)colormap->fadergba : GL_DEFAULTFOG; // Crappy backup coloring if you can't do shaders - if (!cv_glshaders.value || !gl_shadersavailable) + if (!HWR_UseShader()) { // be careful, this may get negative for high lightlevel values. float tint_alpha, fade_alpha; @@ -362,16 +367,16 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool float fflatwidth = 64.0f, fflatheight = 64.0f; INT32 flatflag = 63; boolean texflat = false; - float scrollx = 0.0f, scrolly = 0.0f; + float scrollx = 0.0f, scrolly = 0.0f, anglef = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; - fixed_t tempxsow, tempytow; + float tempxsow, tempytow; pslope_t *slope = NULL; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - int shader; + INT32 shader = SHADER_DEFAULT; // no convex poly were generated for this subsector if (!xsub->planepoly) @@ -499,24 +504,15 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } } - if (angle) // Only needs to be done if there's an altered angle { + tempxsow = flatxref; + tempytow = flatyref; - angle = (InvAngle(angle))>>ANGLETOFINESHIFT; + anglef = ANG2RAD(InvAngle(angle)); - // This needs to be done so that it scrolls in a different direction after rotation like software - /*tempxsow = FLOAT_TO_FIXED(scrollx); - tempytow = FLOAT_TO_FIXED(scrolly); - scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));*/ - - // This needs to be done so everything aligns after rotation - // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does - tempxsow = FLOAT_TO_FIXED(flatxref); - tempytow = FLOAT_TO_FIXED(flatyref); - flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef)); + flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef)); } #define SETUP3DVERT(vert, vx, vy) {\ @@ -535,10 +531,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool /* Need to rotate before translate */\ if (angle) /* Only needs to be done if there's an altered angle */\ {\ - tempxsow = FLOAT_TO_FIXED(vert->s);\ - tempytow = FLOAT_TO_FIXED(vert->t);\ - vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ - vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ + tempxsow = vert->s;\ + tempytow = vert->t;\ + vert->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));\ + vert->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));\ }\ \ vert->x = (vx);\ @@ -568,12 +564,17 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool else PolyFlags |= PF_Masked|PF_Modulated; - if (PolyFlags & PF_Fog) - shader = SHADER_FOG; // fog shader - else if (PolyFlags & PF_Ripple) - shader = SHADER_WATER; // water shader - else - shader = SHADER_FLOOR; // floor shader + if (HWR_UseShader()) + { + if (PolyFlags & PF_Fog) + shader = SHADER_FOG; + else if (PolyFlags & PF_Ripple) + shader = SHADER_WATER; + else + shader = SHADER_FLOOR; + + PolyFlags |= PF_ColorMapped; + } HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); @@ -702,10 +703,12 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) #endif //doplanes -FBITFIELD HWR_GetBlendModeFlag(INT32 ast) +FBITFIELD HWR_GetBlendModeFlag(INT32 style) { - switch (ast) + switch (style) { + case AST_TRANSLUCENT: + return PF_Translucent; case AST_ADD: return PF_Additive; case AST_SUBTRACT: @@ -715,10 +718,8 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast) case AST_MODULATE: return PF_Multiplicative; default: - return PF_Translucent; + return PF_Masked; } - - return 0; } UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) @@ -744,7 +745,7 @@ UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf) { - if (!transtablenum) + if (!transtablenum || style <= AST_COPY || style >= AST_OVERLAY) { pSurf->PolyColor.s.alpha = 0xff; return PF_Masked; @@ -785,8 +786,17 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I // static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { + INT32 shader = SHADER_DEFAULT; + HWR_Lighting(pSurf, lightlevel, wallcolormap); - HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, SHADER_WALL, false); // wall shader + + if (HWR_UseShader()) + { + shader = SHADER_WALL; + blendmode |= PF_ColorMapped; + } + + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, shader, false); } // ========================================================================== @@ -831,7 +841,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) // // HWR_SplitWall // -static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) +static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD polyflags) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts @@ -969,11 +979,11 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, wallVerts[1].y = endbot; if (cutflag & FF_FOG) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture|polyflags, true, lightnum, colormap); else if (cutflag & FF_TRANSLUCENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent|polyflags, false, lightnum, colormap); else - HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); + HWR_ProjectWall(wallVerts, Surf, PF_Masked|polyflags, lightnum, colormap); top = bot; endtop = endbot; @@ -998,11 +1008,11 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, wallVerts[1].y = endbot; if (cutflag & FF_FOG) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture|polyflags, true, lightnum, colormap); else if (cutflag & FF_TRANSLUCENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent|polyflags, false, lightnum, colormap); else - HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); + HWR_ProjectWall(wallVerts, Surf, PF_Masked|polyflags, lightnum, colormap); } // HWR_DrawSkyWall @@ -1104,7 +1114,6 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight) SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight) -#undef SLOPEPARAMS // hack to allow height changes in outdoor areas // This is what gets rid of the upper textures if there should be sky @@ -1183,7 +1192,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_toptexture, &Surf, FF_CUTLEVEL, NULL); + HWR_SplitWall(gl_frontsector, wallVerts, gl_toptexture, &Surf, FF_CUTLEVEL, NULL, 0); else if (grTex->mipmap.flags & TF_TRANSPARENT) HWR_AddTransparentWall(wallVerts, &Surf, gl_toptexture, PF_Environment, false, lightnum, colormap); else @@ -1249,7 +1258,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_bottomtexture, &Surf, FF_CUTLEVEL, NULL); + HWR_SplitWall(gl_frontsector, wallVerts, gl_bottomtexture, &Surf, FF_CUTLEVEL, NULL, 0); else if (grTex->mipmap.flags & TF_TRANSPARENT) HWR_AddTransparentWall(wallVerts, &Surf, gl_bottomtexture, PF_Environment, false, lightnum, colormap); else @@ -1465,13 +1474,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom blendmode = HWR_TranstableToAlpha(gl_curline->polyseg->translucency, &Surf); } + // Render midtextures on two-sided lines with a z-buffer offset. + // This will cause the midtexture appear on top, if a FOF overlaps with it. + blendmode |= PF_Decal; + if (gl_frontsector->numlights) { if (!(blendmode & PF_Masked)) - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_TRANSLUCENT, NULL); + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_TRANSLUCENT, NULL, PF_Decal); else { - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL); + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, PF_Decal); } } else if (!(blendmode & PF_Masked)) @@ -1554,7 +1567,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // I don't think that solid walls can use translucent linedef types... if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL); + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, 0); else { if (grTex->mipmap.flags & TF_TRANSPARENT) @@ -1589,14 +1602,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { ffloor_t * rover; fixed_t highcut = 0, lowcut = 0; + fixed_t lowcutslope, highcutslope; + + // Used for height comparisons and etc across FOFs and slopes + fixed_t high1, highslope1, low1, lowslope1; INT32 texnum; line_t * newline = NULL; // Multi-Property FOF - ///TODO add slope support (fixing cutoffs, proper wall clipping) - maybe just disable highcut/lowcut if either sector or FOF has a slope - /// to allow fun plane intersecting in OGL? But then people would abuse that and make software look bad. :C - highcut = gl_frontsector->ceilingheight < gl_backsector->ceilingheight ? gl_frontsector->ceilingheight : gl_backsector->ceilingheight; - lowcut = gl_frontsector->floorheight > gl_backsector->floorheight ? gl_frontsector->floorheight : gl_backsector->floorheight; + lowcut = max(worldbottom, worldlow); + highcut = min(worldtop, worldhigh); + lowcutslope = max(worldbottomslope, worldlowslope); + highcutslope = min(worldtopslope, worldhighslope); if (gl_backsector->ffloors) { @@ -1618,7 +1635,11 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom continue; if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES) continue; - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) + + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) + + if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture); @@ -1634,10 +1655,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom hS = P_GetFFloorTopZAt (rover, v2x, v2y); l = P_GetFFloorBottomZAt(rover, v1x, v1y); lS = P_GetFFloorBottomZAt(rover, v2x, v2y); - if (!(*rover->t_slope) && !gl_frontsector->c_slope && !gl_backsector->c_slope && h > highcut) - h = hS = highcut; - if (!(*rover->b_slope) && !gl_frontsector->f_slope && !gl_backsector->f_slope && l < lowcut) - l = lS = lowcut; + // Adjust the heights so the FOF does not overlap with top and bottom textures. + if (h >= highcut && hS >= highcutslope) + { + h = highcut; + hS = highcutslope; + } + if (l <= lowcut && lS <= lowcutslope) + { + l = lowcut; + lS = lowcutslope; + } //Hurdler: HW code starts here //FIXME: check if peging is correct // set top/bottom coords @@ -1717,7 +1745,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->flags, rover); + HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->flags, rover, 0); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -1732,7 +1760,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, texnum, &Surf, rover->flags, rover); + HWR_SplitWall(gl_frontsector, wallVerts, texnum, &Surf, rover->flags, rover, 0); else { if (blendmode != PF_Masked) @@ -1764,7 +1792,11 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom continue; if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) continue; - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) + + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) + + if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture); @@ -1779,10 +1811,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom hS = P_GetFFloorTopZAt (rover, v2x, v2y); l = P_GetFFloorBottomZAt(rover, v1x, v1y); lS = P_GetFFloorBottomZAt(rover, v2x, v2y); - if (!(*rover->t_slope) && !gl_frontsector->c_slope && !gl_backsector->c_slope && h > highcut) - h = hS = highcut; - if (!(*rover->b_slope) && !gl_frontsector->f_slope && !gl_backsector->f_slope && l < lowcut) - l = lS = lowcut; + // Adjust the heights so the FOF does not overlap with top and bottom textures. + if (h >= highcut && hS >= highcutslope) + { + h = highcut; + hS = highcutslope; + } + if (l <= lowcut && lS <= lowcutslope) + { + l = lowcut; + lS = lowcutslope; + } //Hurdler: HW code starts here //FIXME: check if peging is correct // set top/bottom coords @@ -1829,7 +1868,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gl_backsector->numlights) - HWR_SplitWall(gl_backsector, wallVerts, 0, &Surf, rover->flags, rover); + HWR_SplitWall(gl_backsector, wallVerts, 0, &Surf, rover->flags, rover, 0); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -1844,7 +1883,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } if (gl_backsector->numlights) - HWR_SplitWall(gl_backsector, wallVerts, texnum, &Surf, rover->flags, rover); + HWR_SplitWall(gl_backsector, wallVerts, texnum, &Surf, rover->flags, rover, 0); else { if (blendmode != PF_Masked) @@ -1856,6 +1895,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } } } +#undef SLOPEPARAMS //Hurdler: end of 3d-floors test } @@ -2659,30 +2699,30 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, FBITFIELD blendmode, UINT8 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { - float height; //constant y for all points on the convex flat polygon - FOutVector *v3d; - INT32 i; - float flatxref,flatyref; + FSurfaceInfo Surf; + FOutVector *v3d; + INT32 shader = SHADER_DEFAULT; + + size_t nrPlaneVerts = polysector->numVertices; + INT32 i; + + float height = FIXED_TO_FLOAT(fixedheight); // constant y for all points on the convex flat polygon + float flatxref, flatyref; float fflatwidth = 64.0f, fflatheight = 64.0f; INT32 flatflag = 63; + boolean texflat = false; + float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; - FSurfaceInfo Surf; fixed_t tempxs, tempyt; - size_t nrPlaneVerts; static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - nrPlaneVerts = polysector->numVertices; - - height = FIXED_TO_FLOAT(fixedheight); - - if (nrPlaneVerts < 3) //not even a triangle ? + if (nrPlaneVerts < 3) // Not even a triangle? return; - - if (nrPlaneVerts > (size_t)UINT16_MAX) // FIXME: exceeds plVerts size + else if (nrPlaneVerts > (size_t)UINT16_MAX) // FIXME: exceeds plVerts size { CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX); return; @@ -2834,7 +2874,6 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, v3d->z = FIXED_TO_FLOAT(polysector->vertices[i]->y); } - HWR_Lighting(&Surf, lightlevel, planecolormap); if (blendmode & PF_Translucent) @@ -2845,7 +2884,13 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, else blendmode |= PF_Masked|PF_Modulated; - HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, SHADER_FLOOR, false); // floor shader + if (HWR_UseShader()) + { + shader = SHADER_FLOOR; + blendmode |= PF_ColorMapped; + } + + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, shader, false); } static void HWR_AddPolyObjectPlanes(void) @@ -3566,6 +3611,8 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) FSurfaceInfo sSurf; float fscale; float fx; float fy; float offset; extracolormap_t *colormap = NULL; + FBITFIELD blendmode = PF_Translucent|PF_Modulated; + INT32 shader = SHADER_DEFAULT; UINT8 i; SINT8 flip = P_MobjFlip(thing); @@ -3658,7 +3705,13 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) HWR_Lighting(&sSurf, 0, colormap); sSurf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated, SHADER_SPRITE, false); // sprite shader + if (HWR_UseShader()) + { + shader = SHADER_SPRITE; + blendmode |= PF_ColorMapped; + } + + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, blendmode, shader, false); } // This is expecting a pointer to an array containing 4 wallVerts for a sprite @@ -3706,6 +3759,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) boolean lightset = true; FBITFIELD blend = 0; FBITFIELD occlusion; + INT32 shader = SHADER_DEFAULT; boolean use_linkdraw_hack = false; UINT8 alpha; @@ -3813,8 +3867,6 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) else if (spr->mobj->frame & FF_TRANSMASK) { INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) - return; blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); } else @@ -3828,6 +3880,12 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) if (!occlusion) use_linkdraw_hack = true; } + if (HWR_UseShader()) + { + shader = SHADER_SPRITE; + blend |= PF_ColorMapped; + } + alpha = Surf.PolyColor.s.alpha; // Start with the lightlevel and colormap from the top of the sprite @@ -3936,7 +3994,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -3965,7 +4023,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -4137,6 +4195,11 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) wallVerts[1].z = wallVerts[2].z = spr->z2; } + // cache the patch in the graphics card memory + //12/12/99: Hurdler: same comment as above (for md2) + //Hurdler: 25/04/2000: now support colormap in hardware mode + HWR_GetMappedPatch(gpatch, spr->colormap); + if (spr->flip) { wallVerts[0].s = wallVerts[3].s = ((GLPatch_t *)gpatch->hardware)->max_s; @@ -4156,11 +4219,6 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) wallVerts[0].t = wallVerts[1].t = ((GLPatch_t *)gpatch->hardware)->max_t; } - // cache the patch in the graphics card memory - //12/12/99: Hurdler: same comment as above (for md2) - //Hurdler: 25/04/2000: now support colormap in hardware mode - HWR_GetMappedPatch(gpatch, spr->colormap); - if (!splat) { // if it has a dispoffset, push it a little towards the camera @@ -4215,6 +4273,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) } { + INT32 shader = SHADER_DEFAULT; FBITFIELD blend = 0; FBITFIELD occlusion; boolean use_linkdraw_hack = false; @@ -4240,8 +4299,6 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else if (spr->mobj->frame & FF_TRANSMASK) { INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) - return; blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); } else @@ -4267,7 +4324,13 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!occlusion) use_linkdraw_hack = true; } - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader + if (HWR_UseShader()) + { + shader = SHADER_SPRITE; + blend |= PF_ColorMapped; + } + + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -4278,6 +4341,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // Sprite drawer for precipitation static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) { + INT32 shader = SHADER_DEFAULT; FBITFIELD blend = 0; FOutVector wallVerts[4]; patch_t *gpatch; @@ -4354,9 +4418,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) if (spr->mobj->frame & FF_TRANSMASK) { INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) - return; - blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); + blend = HWR_SurfaceBlend(AST_TRANSLUCENT, trans, &Surf); } else { @@ -4368,7 +4430,13 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|PF_Occlude; } - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader + if (HWR_UseShader()) + { + shader = SHADER_SPRITE; + blend |= PF_ColorMapped; + } + + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); } #endif @@ -4935,6 +5003,13 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->spritexscale < 1 || thing->spriteyscale < 1) return; + // Visibility check by the blend mode. + if (thing->frame & FF_TRANSMASK) + { + if (!R_BlendLevelVisible(thing->blendmode, (thing->frame & FF_TRANSMASK)>>FF_TRANSSHIFT)) + return; + } + dispoffset = thing->info->dispoffset; this_scale = FIXED_TO_FLOAT(thing->scale); @@ -5266,7 +5341,7 @@ static void HWR_ProjectSprite(mobj_t *thing) else if (vis->mobj->type == MT_METALSONIC_BATTLE) vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); else - vis->colormap = R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + vis->colormap = R_GetTranslationColormap(TC_BOSS, vis->mobj->color, GTC_CACHE); } else if (thing->color) { @@ -5321,6 +5396,13 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) unsigned rot = 0; UINT8 flip; + // Visibility check by the blend mode. + if (thing->frame & FF_TRANSMASK) + { + if (!R_BlendLevelVisible(thing->blendmode, (thing->frame & FF_TRANSMASK)>>FF_TRANSSHIFT)) + return; + } + // transform the origin point tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; tr_y = FIXED_TO_FLOAT(thing->y) - gl_viewy; @@ -5354,7 +5436,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) return; #endif - sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; + sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; // use single rotation for all views lumpoff = sprframe->lumpid[0]; @@ -5647,7 +5729,7 @@ static void HWR_DrawSkyBackground(player_t *player) dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - v[0].s = v[3].s = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[0].s = v[3].s = (-1.0f * angle) / (((float)ANGLE_90-1.0f)*dimensionmultiply); // left v[2].s = v[1].s = v[0].s + (1.0f/dimensionmultiply); // right (or left + 1.0f) // use +angle and -1.0f above instead if you wanted old backwards behavior @@ -6450,24 +6532,29 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, FBITFIELD blendmode = blend; UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha - int shader; + INT32 shader = SHADER_DEFAULT; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting HWR_Lighting(pSurf, lightlevel, wallcolormap); pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting - shader = SHADER_WALL; // wall shader - if (blend & PF_Environment) blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects - if (fogwall) + if (HWR_UseShader()) { - blendmode |= PF_Fog; - shader = SHADER_FOG; // fog shader + if (fogwall) + shader = SHADER_FOG; + else + shader = SHADER_WALL; + + blendmode |= PF_ColorMapped; } + if (fogwall) + blendmode |= PF_Fog; + blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false); } @@ -6510,7 +6597,7 @@ void HWR_DoPostProcessor(player_t *player) Surf.PolyColor.s.alpha = 0xc0; // match software mode - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_AdditiveSource|PF_NoTexture|PF_NoDepthTest); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest); } // Capture the screen for intermission and screen waving @@ -6643,7 +6730,6 @@ void HWR_DrawScreenFinalTexture(int width, int height) HWD.pfnDrawScreenFinalTexture(width, height); } -// jimita 18032019 static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum) { UINT16 i; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4ad09aa3d..218650b53 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -69,7 +69,7 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work UINT8 HWR_GetTranstableAlpha(INT32 transtablenum); -FBITFIELD HWR_GetBlendModeFlag(INT32 ast); +FBITFIELD HWR_GetBlendModeFlag(INT32 style); FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf); FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index ac637dfb7..b66f91e19 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -158,7 +158,7 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ jmp_buf jmpbuf; #endif #endif - png_FILE_p png_FILE; + volatile png_FILE_p png_FILE; //Filename checking fixed ~Monster Iestyn and Golden char *pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename); @@ -777,24 +777,7 @@ static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMi 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) + if (skinnum == TC_ALLWHITE) { // Turn everything white cur->s.red = cur->s.green = cur->s.blue = 255; @@ -1065,6 +1048,15 @@ skippixel: cur->s.alpha = image->s.alpha; } + else 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); + } + } } } @@ -1533,7 +1525,12 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) { nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; if (nextFrame >= mod) - nextFrame = 0; + { + if (spr->mobj->state->frame & FF_SPR2ENDSTATE) + nextFrame--; + else + nextFrame = 0; + } if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; else diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 0f4d2c7bc..9249c034c 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 6967bab74..645a3bbae 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1998-2020 by Sonic Team Junior. +// Copyright (C) 1998-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -910,7 +910,6 @@ void SetupGLFunc4(void) pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); } -// jimita EXPORT boolean HWRAPI(CompileShaders) (void) { #ifdef GL_SHADERS @@ -1301,8 +1300,12 @@ EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *pTexInfo) { if (head->next) head->next->prev = head->prev; + else // no next -> tail is being deleted -> update TexCacheTail + TexCacheTail = head->prev; if (head->prev) head->prev->next = head->next; + else // no prev -> head is being deleted -> update TexCacheHead + TexCacheHead = head->next; free(head); break; } @@ -1576,12 +1579,11 @@ static void SetBlendMode(FBITFIELD flags) case PF_Additive & PF_Blending: case PF_Subtractive & PF_Blending: case PF_ReverseSubtract & PF_Blending: + pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest + break; case PF_Environment & PF_Blending: pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); break; - case PF_AdditiveSource & PF_Blending: - pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest - break; case PF_Multiplicative & PF_Blending: pglBlendFunc(GL_DST_COLOR, GL_ZERO); break; @@ -1620,7 +1622,6 @@ static void SetBlendMode(FBITFIELD flags) break; case PF_Translucent & PF_Blending: case PF_Additive & PF_Blending: - case PF_AdditiveSource & PF_Blending: case PF_Subtractive & PF_Blending: case PF_ReverseSubtract & PF_Blending: case PF_Environment & PF_Blending: @@ -2174,32 +2175,34 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD SetBlend(PolyFlags); //TODO: inline (#pragma..) - // PolyColor if (pSurf) { - // If Modulated, mix the surface colour to the texture + // If modulated, mix the surface colour to the texture if (CurrentPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[pSurf->PolyColor.s.red]; - poly.green = byte2float[pSurf->PolyColor.s.green]; - poly.blue = byte2float[pSurf->PolyColor.s.blue]; - poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; - pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + + // If the surface is either modulated or colormapped, or both + if (CurrentPolyFlags & (PF_Modulated | PF_ColorMapped)) + { + 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]; } - // 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]; + // Only if the surface is colormapped + if (CurrentPolyFlags & PF_ColorMapped) + { + tint.red = byte2float[pSurf->TintColor.s.red]; + tint.green = byte2float[pSurf->TintColor.s.green]; + tint.blue = byte2float[pSurf->TintColor.s.blue]; + tint.alpha = byte2float[pSurf->TintColor.s.alpha]; - // Fade color - fade.red = byte2float[pSurf->FadeColor.s.red]; - fade.green = byte2float[pSurf->FadeColor.s.green]; - fade.blue = byte2float[pSurf->FadeColor.s.blue]; - fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; + 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]; + } } // this test is added for new coronas' code (without depth buffer) @@ -2752,7 +2755,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 fade.alpha = byte2float[Surface->FadeColor.s.alpha]; flags = (Surface->PolyFlags | PF_Modulated); - if (Surface->PolyFlags & (PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative)) + if (Surface->PolyFlags & (PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative)) flags |= PF_Occlude; else if (Surface->PolyColor.s.alpha == 0xFF) flags |= (PF_Occlude | PF_Masked); @@ -3013,7 +3016,6 @@ 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) diff --git a/src/http-mserv.c b/src/http-mserv.c index 7c7d04495..f9134ba50 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7c4f1acf1..e0eaf8fb1 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -686,7 +686,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. - if (LUAh_PlayerMsg(playernum, target, flags, msg)) + if (LUA_HookPlayerMsg(playernum, target, flags, msg)) return; if (spam_eatmsg) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 63d85f1b8..9b7cee2d3 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_addrinfo.c b/src/i_addrinfo.c index e77774549..5dcea1002 100644 --- a/src/i_addrinfo.c +++ b/src/i_addrinfo.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2020 by Sonic Team Junior. +// Copyright (C) 2011-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,7 +20,7 @@ #else #include #endif -#elif !defined (__DJGPP__) +#else #include #include #include diff --git a/src/i_addrinfo.h b/src/i_addrinfo.h index 7ae006719..397a1969d 100644 --- a/src/i_addrinfo.h +++ b/src/i_addrinfo.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2020 by Sonic Team Junior. +// Copyright (C) 2011-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_joy.h b/src/i_joy.h index 2a2797fc4..0c7c8dd3f 100644 --- a/src/i_joy.h +++ b/src/i_joy.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_net.h b/src/i_net.h index 5d93f191e..dbc82db65 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_sound.h b/src/i_sound.h index d45c0b323..e38a17626 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_system.h b/src/i_system.h index 12f0d751d..e046fd620 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -314,4 +314,16 @@ const char *I_ClipboardPaste(void); void I_RegisterSysCommands(void); +/** \brief Return the position of the cursor relative to the top-left window corner. +*/ +void I_GetCursorPosition(INT32 *x, INT32 *y); + +/** \brief Returns whether the mouse is grabbed +*/ +boolean I_GetMouseGrab(void); + +/** \brief Sets whether the mouse is grabbed +*/ +void I_SetMouseGrab(boolean grab); + #endif diff --git a/src/i_tcp.c b/src/i_tcp.c index ab8a69a9f..cae97a7d1 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -64,7 +64,7 @@ #include #include - #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) + #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) #include #endif // UNIXCOMMON #endif @@ -107,15 +107,6 @@ #endif #endif // USE_WINSOCK - #ifdef __DJGPP__ - #ifdef WATTCP // Alam_GBC: Wattcp may need this - #include - #define strerror strerror_s - #else // wattcp - #include - #endif // libsocket - #endif // djgpp - typedef union { struct sockaddr any; @@ -149,32 +140,22 @@ #include "doomstat.h" -// win32 or djgpp -#if defined (USE_WINSOCK) || defined (__DJGPP__) +// win32 +#ifdef USE_WINSOCK // winsock stuff (in winsock a socket is not a file) #define ioctl ioctlsocket #define close closesocket #endif #include "i_addrinfo.h" - -#ifdef __DJGPP__ - -#ifdef WATTCP #define SELECTTEST -#endif - -#else -#define SELECTTEST -#endif - #define DEFAULTPORT "5029" #if defined (USE_WINSOCK) && !defined (NONET) typedef SOCKET SOCKET_TYPE; #define ERRSOCKET (SOCKET_ERROR) #else - #if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) + #if defined (__unix__) || defined (__APPLE__) || defined (__HAIKU__) typedef int SOCKET_TYPE; #else typedef unsigned long SOCKET_TYPE; @@ -184,7 +165,7 @@ #ifndef NONET // define socklen_t in DOS/Windows if it is not already defined - #if (defined (WATTCP) && !defined (__libsocket_socklen_t)) || defined (USE_WINSOCK1) + #ifdef USE_WINSOCK1 typedef int socklen_t; #endif static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET}; @@ -207,19 +188,6 @@ static const char *serverport_name = DEFAULTPORT; static const char *clientport_name;/* any port */ #ifndef NONET - -#ifdef WATTCP -static void wattcp_outch(char s) -{ - static char old = '\0'; - char pr[2] = {s,0}; - if (s == old && old == ' ') return; - else old = s; - if (s == '\r') CONS_Printf("\n"); - else if (s != '\n') CONS_Printf(pr); -} -#endif - #ifdef USE_WINSOCK // stupid microsoft makes things complicated static char *get_WSAErrorStr(int e) @@ -764,11 +732,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen int opt; socklen_t opts; #ifdef FIONBIO -#ifdef WATTCP - char trueval = true; -#else unsigned long trueval = true; -#endif #endif mysockaddr_t straddr; struct sockaddr_in sin; @@ -1138,61 +1102,7 @@ boolean I_InitTcpDriver(void) CONS_Debug(DBG_NETPLAY, "WinSock description: %s\n",WSAData.szDescription); CONS_Debug(DBG_NETPLAY, "WinSock System Status: %s\n",WSAData.szSystemStatus); #endif -#ifdef __DJGPP__ -#ifdef WATTCP // Alam_GBC: survive bootp, dhcp, rarp and wattcp/pktdrv from failing to load - survive_eth = 1; // would be needed to not exit if pkt_eth_init() fails - survive_bootp = 1; // ditto for BOOTP - survive_dhcp = 1; // ditto for DHCP/RARP - survive_rarp = 1; - //_watt_do_exit = false; - //_watt_handle_cbreak = false; - //_watt_no_config = true; - _outch = wattcp_outch; - init_misc(); -//#ifdef DEBUGFILE - dbug_init(); -//#endif - switch (sock_init()) - { - case 0: - init_tcp_driver = true; - break; - case 3: - CONS_Debug(DBG_NETPLAY, "No packet driver detected\n"); - break; - case 4: - CONS_Debug(DBG_NETPLAY, "Error while talking to packet driver\n"); - break; - case 5: - CONS_Debug(DBG_NETPLAY, "BOOTP failed\n"); - break; - case 6: - CONS_Debug(DBG_NETPLAY, "DHCP failed\n"); - break; - case 7: - CONS_Debug(DBG_NETPLAY, "RARP failed\n"); - break; - case 8: - CONS_Debug(DBG_NETPLAY, "TCP/IP failed\n"); - break; - case 9: - CONS_Debug(DBG_NETPLAY, "PPPoE login/discovery failed\n"); - break; - default: - CONS_Debug(DBG_NETPLAY, "Unknown error with TCP/IP stack\n"); - break; - } - hires_timer(0); -#else // wattcp - if (__lsck_init()) - init_tcp_driver = true; - else - CONS_Debug(DBG_NETPLAY, "No TCP/IP driver detected\n"); -#endif // libsocket -#endif // __DJGPP__ -#ifndef __DJGPP__ init_tcp_driver = true; -#endif } #endif if (!tcp_was_up && init_tcp_driver) @@ -1217,10 +1127,8 @@ static void SOCK_CloseSocket(void) if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET && FD_ISSET(mysockets[i], &masterset)) { -#if !defined (__DJGPP__) || defined (WATTCP) FD_CLR(mysockets[i], &masterset); close(mysockets[i]); -#endif } mysockets[i] = ERRSOCKET; } @@ -1237,14 +1145,6 @@ void I_ShutdownTcpDriver(void) WS_addrinfocleanup(); WSACleanup(); #endif -#ifdef __DJGPP__ -#ifdef WATTCP // wattcp - //_outch = NULL; - sock_exit(); -#else - __lsck_uninit(); -#endif // libsocket -#endif // __DJGPP__ CONS_Printf("shut down\n"); init_tcp_driver = false; #endif diff --git a/src/i_tcp.h b/src/i_tcp.h index 738b8b4d1..785734415 100644 --- a/src/i_tcp.h +++ b/src/i_tcp.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_threads.h b/src/i_threads.h index ecb9fce67..bc752181f 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_video.h b/src/i_video.h index ab48881d4..2d07fcf10 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/info.c b/src/info.c index ee836a372..efcf1c044 100644 --- a/src/info.c +++ b/src/info.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -13481,7 +13481,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 32*FRACUNIT, // speed 30*FRACUNIT, // radius 60*FRACUNIT, // height - 0, // display offset + -1, // display offset 100, // mass 0, // damage sfx_None, // activesound @@ -21761,7 +21761,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM - {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY + {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY // super diff --git a/src/info.h b/src/info.h index 60e970246..031a08b43 100644 --- a/src/info.h +++ b/src/info.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/keys.h b/src/keys.h index 6cdd7956c..b19259320 100644 --- a/src/keys.h +++ b/src/keys.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/libdivide.h b/src/libdivide.h new file mode 100644 index 000000000..1a589c7e5 --- /dev/null +++ b/src/libdivide.h @@ -0,0 +1,2111 @@ +// libdivide.h - Optimized integer division +// https://libdivide.com +// +// Copyright (C) 2010 - 2019 ridiculous_fish, +// Copyright (C) 2016 - 2019 Kim Walisch, +// +// libdivide is dual-licensed under the Boost or zlib licenses. +// You may use libdivide under the terms of either of these. +// See LICENSE.txt in the libdivide source code repository for more details. + + +// NOTICE: This is an altered source version of libdivide. +// Libdivide is used here under the terms of the zlib license. +// Here is the zlib license text from https://github.com/ridiculousfish/libdivide/blob/master/LICENSE.txt +/* + zlib License + ------------ + + Copyright (C) 2010 - 2019 ridiculous_fish, + Copyright (C) 2016 - 2019 Kim Walisch, + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +// This version of libdivide has been modified for use with SRB2. +// Changes made include: +// - unused parts commented out (to avoid the need to fix C90 compilation issues with them) +// - C90 compilation issues fixed with used parts +// - use I_Error for errors + +#ifndef LIBDIVIDE_H +#define LIBDIVIDE_H + +#define LIBDIVIDE_VERSION "3.0" +#define LIBDIVIDE_VERSION_MAJOR 3 +#define LIBDIVIDE_VERSION_MINOR 0 + +#include + +#if defined(__cplusplus) + #include + #include + #include +#else + #include + #include +#endif + +#if defined(LIBDIVIDE_AVX512) + #include +#elif defined(LIBDIVIDE_AVX2) + #include +#elif defined(LIBDIVIDE_SSE2) + #include +#endif + +#if defined(_MSC_VER) + #include + // disable warning C4146: unary minus operator applied + // to unsigned type, result still unsigned + #pragma warning(disable: 4146) + #define LIBDIVIDE_VC +#endif + +#if !defined(__has_builtin) + #define __has_builtin(x) 0 +#endif + +#if defined(__SIZEOF_INT128__) + #define HAS_INT128_T + // clang-cl on Windows does not yet support 128-bit division + #if !(defined(__clang__) && defined(LIBDIVIDE_VC)) + #define HAS_INT128_DIV + #endif +#endif + +#if defined(__x86_64__) || defined(_M_X64) + #define LIBDIVIDE_X86_64 +#endif + +#if defined(__i386__) + #define LIBDIVIDE_i386 +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define LIBDIVIDE_GCC_STYLE_ASM +#endif + +#if defined(__cplusplus) || defined(LIBDIVIDE_VC) + #define LIBDIVIDE_FUNCTION __FUNCTION__ +#else + #define LIBDIVIDE_FUNCTION __func__ +#endif + +#define LIBDIVIDE_ERROR(msg) \ + I_Error("libdivide.h:%d: %s(): Error: %s\n", \ + __LINE__, LIBDIVIDE_FUNCTION, msg); + +#if defined(LIBDIVIDE_ASSERTIONS_ON) + #define LIBDIVIDE_ASSERT(x) \ + if (!(x)) { \ + I_Error("libdivide.h:%d: %s(): Assertion failed: %s\n", \ + __LINE__, LIBDIVIDE_FUNCTION, #x); \ + } +#else + #define LIBDIVIDE_ASSERT(x) +#endif + +#ifdef __cplusplus +namespace libdivide { +#endif + +// pack divider structs to prevent compilers from padding. +// This reduces memory usage by up to 43% when using a large +// array of libdivide dividers and improves performance +// by up to 10% because of reduced memory bandwidth. +#pragma pack(push, 1) + +struct libdivide_u32_t { + uint32_t magic; + uint8_t more; +}; + +struct libdivide_s32_t { + int32_t magic; + uint8_t more; +}; + +struct libdivide_u64_t { + uint64_t magic; + uint8_t more; +}; + +struct libdivide_s64_t { + int64_t magic; + uint8_t more; +}; + +struct libdivide_u32_branchfree_t { + uint32_t magic; + uint8_t more; +}; + +struct libdivide_s32_branchfree_t { + int32_t magic; + uint8_t more; +}; + +struct libdivide_u64_branchfree_t { + uint64_t magic; + uint8_t more; +}; + +struct libdivide_s64_branchfree_t { + int64_t magic; + uint8_t more; +}; + +#pragma pack(pop) + +// Explanation of the "more" field: +// +// * Bits 0-5 is the shift value (for shift path or mult path). +// * Bit 6 is the add indicator for mult path. +// * Bit 7 is set if the divisor is negative. We use bit 7 as the negative +// divisor indicator so that we can efficiently use sign extension to +// create a bitmask with all bits set to 1 (if the divisor is negative) +// or 0 (if the divisor is positive). +// +// u32: [0-4] shift value +// [5] ignored +// [6] add indicator +// magic number of 0 indicates shift path +// +// s32: [0-4] shift value +// [5] ignored +// [6] add indicator +// [7] indicates negative divisor +// magic number of 0 indicates shift path +// +// u64: [0-5] shift value +// [6] add indicator +// magic number of 0 indicates shift path +// +// s64: [0-5] shift value +// [6] add indicator +// [7] indicates negative divisor +// magic number of 0 indicates shift path +// +// In s32 and s64 branchfree modes, the magic number is negated according to +// whether the divisor is negated. In branchfree strategy, it is not negated. + +enum { + LIBDIVIDE_32_SHIFT_MASK = 0x1F, + LIBDIVIDE_64_SHIFT_MASK = 0x3F, + LIBDIVIDE_ADD_MARKER = 0x40, + LIBDIVIDE_NEGATIVE_DIVISOR = 0x80 +}; + +//static inline struct libdivide_s32_t libdivide_s32_gen(int32_t d); +static inline struct libdivide_u32_t libdivide_u32_gen(uint32_t d); +//static inline struct libdivide_s64_t libdivide_s64_gen(int64_t d); +//static inline struct libdivide_u64_t libdivide_u64_gen(uint64_t d); + +/*static inline struct libdivide_s32_branchfree_t libdivide_s32_branchfree_gen(int32_t d); +static inline struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t d); +static inline struct libdivide_s64_branchfree_t libdivide_s64_branchfree_gen(int64_t d); +static inline struct libdivide_u64_branchfree_t libdivide_u64_branchfree_gen(uint64_t d);*/ + +//static inline int32_t libdivide_s32_do(int32_t numer, const struct libdivide_s32_t *denom); +static inline uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom); +//static inline int64_t libdivide_s64_do(int64_t numer, const struct libdivide_s64_t *denom); +//static inline uint64_t libdivide_u64_do(uint64_t numer, const struct libdivide_u64_t *denom); + +/*static inline int32_t libdivide_s32_branchfree_do(int32_t numer, const struct libdivide_s32_branchfree_t *denom); +static inline uint32_t libdivide_u32_branchfree_do(uint32_t numer, const struct libdivide_u32_branchfree_t *denom); +static inline int64_t libdivide_s64_branchfree_do(int64_t numer, const struct libdivide_s64_branchfree_t *denom); +static inline uint64_t libdivide_u64_branchfree_do(uint64_t numer, const struct libdivide_u64_branchfree_t *denom);*/ + +/*static inline int32_t libdivide_s32_recover(const struct libdivide_s32_t *denom); +static inline uint32_t libdivide_u32_recover(const struct libdivide_u32_t *denom); +static inline int64_t libdivide_s64_recover(const struct libdivide_s64_t *denom); +static inline uint64_t libdivide_u64_recover(const struct libdivide_u64_t *denom);*/ + +/*static inline int32_t libdivide_s32_branchfree_recover(const struct libdivide_s32_branchfree_t *denom); +static inline uint32_t libdivide_u32_branchfree_recover(const struct libdivide_u32_branchfree_t *denom); +static inline int64_t libdivide_s64_branchfree_recover(const struct libdivide_s64_branchfree_t *denom); +static inline uint64_t libdivide_u64_branchfree_recover(const struct libdivide_u64_branchfree_t *denom);*/ + +//////// Internal Utility Functions + +static inline uint32_t libdivide_mullhi_u32(uint32_t x, uint32_t y) { + uint64_t xl = x, yl = y; + uint64_t rl = xl * yl; + return (uint32_t)(rl >> 32); +} + +static inline int32_t libdivide_mullhi_s32(int32_t x, int32_t y) { + int64_t xl = x, yl = y; + int64_t rl = xl * yl; + // needs to be arithmetic shift + return (int32_t)(rl >> 32); +} + +static inline uint64_t libdivide_mullhi_u64(uint64_t x, uint64_t y) { +#if defined(LIBDIVIDE_VC) && \ + defined(LIBDIVIDE_X86_64) + return __umulh(x, y); +#elif defined(HAS_INT128_T) + __uint128_t xl = x, yl = y; + __uint128_t rl = xl * yl; + return (uint64_t)(rl >> 64); +#else + // full 128 bits are x0 * y0 + (x0 * y1 << 32) + (x1 * y0 << 32) + (x1 * y1 << 64) + uint32_t mask = 0xFFFFFFFF; + uint32_t x0 = (uint32_t)(x & mask); + uint32_t x1 = (uint32_t)(x >> 32); + uint32_t y0 = (uint32_t)(y & mask); + uint32_t y1 = (uint32_t)(y >> 32); + uint32_t x0y0_hi = libdivide_mullhi_u32(x0, y0); + uint64_t x0y1 = x0 * (uint64_t)y1; + uint64_t x1y0 = x1 * (uint64_t)y0; + uint64_t x1y1 = x1 * (uint64_t)y1; + uint64_t temp = x1y0 + x0y0_hi; + uint64_t temp_lo = temp & mask; + uint64_t temp_hi = temp >> 32; + + return x1y1 + temp_hi + ((temp_lo + x0y1) >> 32); +#endif +} + +static inline int64_t libdivide_mullhi_s64(int64_t x, int64_t y) { +#if defined(LIBDIVIDE_VC) && \ + defined(LIBDIVIDE_X86_64) + return __mulh(x, y); +#elif defined(HAS_INT128_T) + __int128_t xl = x, yl = y; + __int128_t rl = xl * yl; + return (int64_t)(rl >> 64); +#else + // full 128 bits are x0 * y0 + (x0 * y1 << 32) + (x1 * y0 << 32) + (x1 * y1 << 64) + uint32_t mask = 0xFFFFFFFF; + uint32_t x0 = (uint32_t)(x & mask); + uint32_t y0 = (uint32_t)(y & mask); + int32_t x1 = (int32_t)(x >> 32); + int32_t y1 = (int32_t)(y >> 32); + uint32_t x0y0_hi = libdivide_mullhi_u32(x0, y0); + int64_t t = x1 * (int64_t)y0 + x0y0_hi; + int64_t w1 = x0 * (int64_t)y1 + (t & mask); + + return x1 * (int64_t)y1 + (t >> 32) + (w1 >> 32); +#endif +} + +static inline int32_t libdivide_count_leading_zeros32(uint32_t val) { +#if defined(__GNUC__) || \ + __has_builtin(__builtin_clz) + // Fast way to count leading zeros + return __builtin_clz(val); +#elif defined(LIBDIVIDE_VC) + unsigned long result; + if (_BitScanReverse(&result, val)) { + return 31 - result; + } + return 0; +#else + if (val == 0) + return 32; + int32_t result = 8; + uint32_t hi = 0xFFU << 24; + while ((val & hi) == 0) { + hi >>= 8; + result += 8; + } + while (val & hi) { + result -= 1; + hi <<= 1; + } + return result; +#endif +} + +static inline int32_t libdivide_count_leading_zeros64(uint64_t val) { +#if defined(__GNUC__) || \ + __has_builtin(__builtin_clzll) + // Fast way to count leading zeros + return __builtin_clzll(val); +#elif defined(LIBDIVIDE_VC) && defined(_WIN64) + unsigned long result; + if (_BitScanReverse64(&result, val)) { + return 63 - result; + } + return 0; +#else + uint32_t hi = val >> 32; + uint32_t lo = val & 0xFFFFFFFF; + if (hi != 0) return libdivide_count_leading_zeros32(hi); + return 32 + libdivide_count_leading_zeros32(lo); +#endif +} + +// libdivide_64_div_32_to_32: divides a 64-bit uint {u1, u0} by a 32-bit +// uint {v}. The result must fit in 32 bits. +// Returns the quotient directly and the remainder in *r +static inline uint32_t libdivide_64_div_32_to_32(uint32_t u1, uint32_t u0, uint32_t v, uint32_t *r) { +#if (defined(LIBDIVIDE_i386) || defined(LIBDIVIDE_X86_64)) && \ + defined(LIBDIVIDE_GCC_STYLE_ASM) + uint32_t result; + __asm__("divl %[v]" + : "=a"(result), "=d"(*r) + : [v] "r"(v), "a"(u0), "d"(u1) + ); + return result; +#else + uint64_t n = ((uint64_t)u1 << 32) | u0; + uint32_t result = (uint32_t)(n / v); + *r = (uint32_t)(n - result * (uint64_t)v); + return result; +#endif +} + +// libdivide_128_div_64_to_64: divides a 128-bit uint {u1, u0} by a 64-bit +// uint {v}. The result must fit in 64 bits. +// Returns the quotient directly and the remainder in *r +/*static uint64_t libdivide_128_div_64_to_64(uint64_t u1, uint64_t u0, uint64_t v, uint64_t *r) { +#if defined(LIBDIVIDE_X86_64) && \ + defined(LIBDIVIDE_GCC_STYLE_ASM) + uint64_t result; + __asm__("divq %[v]" + : "=a"(result), "=d"(*r) + : [v] "r"(v), "a"(u0), "d"(u1) + ); + return result; +#elif defined(HAS_INT128_T) && \ + defined(HAS_INT128_DIV) + __uint128_t n = ((__uint128_t)u1 << 64) | u0; + uint64_t result = (uint64_t)(n / v); + *r = (uint64_t)(n - result * (__uint128_t)v); + return result; +#else + // Code taken from Hacker's Delight: + // http://www.hackersdelight.org/HDcode/divlu.c. + // License permits inclusion here per: + // http://www.hackersdelight.org/permissions.htm + + const uint64_t b = (1ULL << 32); // Number base (32 bits) + uint64_t un1, un0; // Norm. dividend LSD's + uint64_t vn1, vn0; // Norm. divisor digits + uint64_t q1, q0; // Quotient digits + uint64_t un64, un21, un10; // Dividend digit pairs + uint64_t rhat; // A remainder + int32_t s; // Shift amount for norm + + // If overflow, set rem. to an impossible value, + // and return the largest possible quotient + if (u1 >= v) { + *r = (uint64_t) -1; + return (uint64_t) -1; + } + + // count leading zeros + s = libdivide_count_leading_zeros64(v); + if (s > 0) { + // Normalize divisor + v = v << s; + un64 = (u1 << s) | (u0 >> (64 - s)); + un10 = u0 << s; // Shift dividend left + } else { + // Avoid undefined behavior of (u0 >> 64). + // The behavior is undefined if the right operand is + // negative, or greater than or equal to the length + // in bits of the promoted left operand. + un64 = u1; + un10 = u0; + } + + // Break divisor up into two 32-bit digits + vn1 = v >> 32; + vn0 = v & 0xFFFFFFFF; + + // Break right half of dividend into two digits + un1 = un10 >> 32; + un0 = un10 & 0xFFFFFFFF; + + // Compute the first quotient digit, q1 + q1 = un64 / vn1; + rhat = un64 - q1 * vn1; + + while (q1 >= b || q1 * vn0 > b * rhat + un1) { + q1 = q1 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + // Multiply and subtract + un21 = un64 * b + un1 - q1 * v; + + // Compute the second quotient digit + q0 = un21 / vn1; + rhat = un21 - q0 * vn1; + + while (q0 >= b || q0 * vn0 > b * rhat + un0) { + q0 = q0 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + *r = (un21 * b + un0 - q0 * v) >> s; + return q1 * b + q0; +#endif +}*/ + +// Bitshift a u128 in place, left (signed_shift > 0) or right (signed_shift < 0) +static inline void libdivide_u128_shift(uint64_t *u1, uint64_t *u0, int32_t signed_shift) { + if (signed_shift > 0) { + uint32_t shift = signed_shift; + *u1 <<= shift; + *u1 |= *u0 >> (64 - shift); + *u0 <<= shift; + } + else if (signed_shift < 0) { + uint32_t shift = -signed_shift; + *u0 >>= shift; + *u0 |= *u1 << (64 - shift); + *u1 >>= shift; + } +} + +// Computes a 128 / 128 -> 64 bit division, with a 128 bit remainder. +/*static uint64_t libdivide_128_div_128_to_64(uint64_t u_hi, uint64_t u_lo, uint64_t v_hi, uint64_t v_lo, uint64_t *r_hi, uint64_t *r_lo) { +#if defined(HAS_INT128_T) && \ + defined(HAS_INT128_DIV) + __uint128_t ufull = u_hi; + __uint128_t vfull = v_hi; + ufull = (ufull << 64) | u_lo; + vfull = (vfull << 64) | v_lo; + uint64_t res = (uint64_t)(ufull / vfull); + __uint128_t remainder = ufull - (vfull * res); + *r_lo = (uint64_t)remainder; + *r_hi = (uint64_t)(remainder >> 64); + return res; +#else + // Adapted from "Unsigned Doubleword Division" in Hacker's Delight + // We want to compute u / v + typedef struct { uint64_t hi; uint64_t lo; } u128_t; + u128_t u = {u_hi, u_lo}; + u128_t v = {v_hi, v_lo}; + + if (v.hi == 0) { + // divisor v is a 64 bit value, so we just need one 128/64 division + // Note that we are simpler than Hacker's Delight here, because we know + // the quotient fits in 64 bits whereas Hacker's Delight demands a full + // 128 bit quotient + *r_hi = 0; + return libdivide_128_div_64_to_64(u.hi, u.lo, v.lo, r_lo); + } + // Here v >= 2**64 + // We know that v.hi != 0, so count leading zeros is OK + // We have 0 <= n <= 63 + uint32_t n = libdivide_count_leading_zeros64(v.hi); + + // Normalize the divisor so its MSB is 1 + u128_t v1t = v; + libdivide_u128_shift(&v1t.hi, &v1t.lo, n); + uint64_t v1 = v1t.hi; // i.e. v1 = v1t >> 64 + + // To ensure no overflow + u128_t u1 = u; + libdivide_u128_shift(&u1.hi, &u1.lo, -1); + + // Get quotient from divide unsigned insn. + uint64_t rem_ignored; + uint64_t q1 = libdivide_128_div_64_to_64(u1.hi, u1.lo, v1, &rem_ignored); + + // Undo normalization and division of u by 2. + u128_t q0 = {0, q1}; + libdivide_u128_shift(&q0.hi, &q0.lo, n); + libdivide_u128_shift(&q0.hi, &q0.lo, -63); + + // Make q0 correct or too small by 1 + // Equivalent to `if (q0 != 0) q0 = q0 - 1;` + if (q0.hi != 0 || q0.lo != 0) { + q0.hi -= (q0.lo == 0); // borrow + q0.lo -= 1; + } + + // Now q0 is correct. + // Compute q0 * v as q0v + // = (q0.hi << 64 + q0.lo) * (v.hi << 64 + v.lo) + // = (q0.hi * v.hi << 128) + (q0.hi * v.lo << 64) + + // (q0.lo * v.hi << 64) + q0.lo * v.lo) + // Each term is 128 bit + // High half of full product (upper 128 bits!) are dropped + u128_t q0v = {0, 0}; + q0v.hi = q0.hi*v.lo + q0.lo*v.hi + libdivide_mullhi_u64(q0.lo, v.lo); + q0v.lo = q0.lo*v.lo; + + // Compute u - q0v as u_q0v + // This is the remainder + u128_t u_q0v = u; + u_q0v.hi -= q0v.hi + (u.lo < q0v.lo); // second term is borrow + u_q0v.lo -= q0v.lo; + + // Check if u_q0v >= v + // This checks if our remainder is larger than the divisor + if ((u_q0v.hi > v.hi) || + (u_q0v.hi == v.hi && u_q0v.lo >= v.lo)) { + // Increment q0 + q0.lo += 1; + q0.hi += (q0.lo == 0); // carry + + // Subtract v from remainder + u_q0v.hi -= v.hi + (u_q0v.lo < v.lo); + u_q0v.lo -= v.lo; + } + + *r_hi = u_q0v.hi; + *r_lo = u_q0v.lo; + + LIBDIVIDE_ASSERT(q0.hi == 0); + return q0.lo; +#endif +}*/ + +////////// UINT32 + +static inline struct libdivide_u32_t libdivide_internal_u32_gen(uint32_t d, int branchfree) { + struct libdivide_u32_t result; + uint32_t floor_log_2_d; + + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + floor_log_2_d = 31 - libdivide_count_leading_zeros32(d); + + // Power of 2 + if ((d & (d - 1)) == 0) { + // We need to subtract 1 from the shift value in case of an unsigned + // branchfree divider because there is a hardcoded right shift by 1 + // in its division algorithm. Because of this we also need to add back + // 1 in its recovery algorithm. + result.magic = 0; + result.more = (uint8_t)(floor_log_2_d - (branchfree != 0)); + } else { + uint8_t more; + uint32_t rem, proposed_m; + uint32_t e; + proposed_m = libdivide_64_div_32_to_32(1U << floor_log_2_d, 0, d, &rem); + + LIBDIVIDE_ASSERT(rem > 0 && rem < d); + e = d - rem; + + // This power works if e < 2**floor_log_2_d. + if (!branchfree && (e < (1U << floor_log_2_d))) { + // This power works + more = floor_log_2_d; + } else { + // We have to use the general 33-bit algorithm. We need to compute + // (2**power) / d. However, we already have (2**(power-1))/d and + // its remainder. By doubling both, and then correcting the + // remainder, we can compute the larger division. + // don't care about overflow here - in fact, we expect it + const uint32_t twice_rem = rem + rem; + proposed_m += proposed_m; + if (twice_rem >= d || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + result.magic = 1 + proposed_m; + result.more = more; + // result.more's shift should in general be ceil_log_2_d. But if we + // used the smaller power, we subtract one from the shift because we're + // using the smaller power. If we're using the larger power, we + // subtract one from the shift because it's taken care of by the add + // indicator. So floor_log_2_d happens to be correct in both cases. + } + return result; +} + +struct libdivide_u32_t libdivide_u32_gen(uint32_t d) { + return libdivide_internal_u32_gen(d, 0); +} + +/*struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t d) { + if (d == 1) { + LIBDIVIDE_ERROR("branchfree divider must be != 1"); + } + struct libdivide_u32_t tmp = libdivide_internal_u32_gen(d, 1); + struct libdivide_u32_branchfree_t ret = {tmp.magic, (uint8_t)(tmp.more & LIBDIVIDE_32_SHIFT_MASK)}; + return ret; +}*/ + +uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return numer >> more; + } + else { + uint32_t q = libdivide_mullhi_u32(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + uint32_t t = ((numer - q) >> 1) + q; + return t >> (more & LIBDIVIDE_32_SHIFT_MASK); + } + else { + // All upper bits are 0, + // don't need to mask them off. + return q >> more; + } + } +} + +/*uint32_t libdivide_u32_branchfree_do(uint32_t numer, const struct libdivide_u32_branchfree_t *denom) { + uint32_t q = libdivide_mullhi_u32(denom->magic, numer); + uint32_t t = ((numer - q) >> 1) + q; + return t >> denom->more; +} + +uint32_t libdivide_u32_recover(const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + return 1U << shift; + } else if (!(more & LIBDIVIDE_ADD_MARKER)) { + // We compute q = n/d = n*m / 2^(32 + shift) + // Therefore we have d = 2^(32 + shift) / m + // We need to ceil it. + // We know d is not a power of 2, so m is not a power of 2, + // so we can just add 1 to the floor + uint32_t hi_dividend = 1U << shift; + uint32_t rem_ignored; + return 1 + libdivide_64_div_32_to_32(hi_dividend, 0, denom->magic, &rem_ignored); + } else { + // Here we wish to compute d = 2^(32+shift+1)/(m+2^32). + // Notice (m + 2^32) is a 33 bit number. Use 64 bit division for now + // Also note that shift may be as high as 31, so shift + 1 will + // overflow. So we have to compute it as 2^(32+shift)/(m+2^32), and + // then double the quotient and remainder. + uint64_t half_n = 1ULL << (32 + shift); + uint64_t d = (1ULL << 32) | denom->magic; + // Note that the quotient is guaranteed <= 32 bits, but the remainder + // may need 33! + uint32_t half_q = (uint32_t)(half_n / d); + uint64_t rem = half_n % d; + // We computed 2^(32+shift)/(m+2^32) + // Need to double it, and then add 1 to the quotient if doubling th + // remainder would increase the quotient. + // Note that rem<<1 cannot overflow, since rem < d and d is 33 bits + uint32_t full_q = half_q + half_q + ((rem<<1) >= d); + + // We rounded down in gen (hence +1) + return full_q + 1; + } +} + +uint32_t libdivide_u32_branchfree_recover(const struct libdivide_u32_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + return 1U << (shift + 1); + } else { + // Here we wish to compute d = 2^(32+shift+1)/(m+2^32). + // Notice (m + 2^32) is a 33 bit number. Use 64 bit division for now + // Also note that shift may be as high as 31, so shift + 1 will + // overflow. So we have to compute it as 2^(32+shift)/(m+2^32), and + // then double the quotient and remainder. + uint64_t half_n = 1ULL << (32 + shift); + uint64_t d = (1ULL << 32) | denom->magic; + // Note that the quotient is guaranteed <= 32 bits, but the remainder + // may need 33! + uint32_t half_q = (uint32_t)(half_n / d); + uint64_t rem = half_n % d; + // We computed 2^(32+shift)/(m+2^32) + // Need to double it, and then add 1 to the quotient if doubling th + // remainder would increase the quotient. + // Note that rem<<1 cannot overflow, since rem < d and d is 33 bits + uint32_t full_q = half_q + half_q + ((rem<<1) >= d); + + // We rounded down in gen (hence +1) + return full_q + 1; + } +}*/ + +/////////// UINT64 + +/*static inline struct libdivide_u64_t libdivide_internal_u64_gen(uint64_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_u64_t result; + uint32_t floor_log_2_d = 63 - libdivide_count_leading_zeros64(d); + + // Power of 2 + if ((d & (d - 1)) == 0) { + // We need to subtract 1 from the shift value in case of an unsigned + // branchfree divider because there is a hardcoded right shift by 1 + // in its division algorithm. Because of this we also need to add back + // 1 in its recovery algorithm. + result.magic = 0; + result.more = (uint8_t)(floor_log_2_d - (branchfree != 0)); + } else { + uint64_t proposed_m, rem; + uint8_t more; + // (1 << (64 + floor_log_2_d)) / d + proposed_m = libdivide_128_div_64_to_64(1ULL << floor_log_2_d, 0, d, &rem); + + LIBDIVIDE_ASSERT(rem > 0 && rem < d); + const uint64_t e = d - rem; + + // This power works if e < 2**floor_log_2_d. + if (!branchfree && e < (1ULL << floor_log_2_d)) { + // This power works + more = floor_log_2_d; + } else { + // We have to use the general 65-bit algorithm. We need to compute + // (2**power) / d. However, we already have (2**(power-1))/d and + // its remainder. By doubling both, and then correcting the + // remainder, we can compute the larger division. + // don't care about overflow here - in fact, we expect it + proposed_m += proposed_m; + const uint64_t twice_rem = rem + rem; + if (twice_rem >= d || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + result.magic = 1 + proposed_m; + result.more = more; + // result.more's shift should in general be ceil_log_2_d. But if we + // used the smaller power, we subtract one from the shift because we're + // using the smaller power. If we're using the larger power, we + // subtract one from the shift because it's taken care of by the add + // indicator. So floor_log_2_d happens to be correct in both cases, + // which is why we do it outside of the if statement. + } + return result; +} + +struct libdivide_u64_t libdivide_u64_gen(uint64_t d) { + return libdivide_internal_u64_gen(d, 0); +} + +struct libdivide_u64_branchfree_t libdivide_u64_branchfree_gen(uint64_t d) { + if (d == 1) { + LIBDIVIDE_ERROR("branchfree divider must be != 1"); + } + struct libdivide_u64_t tmp = libdivide_internal_u64_gen(d, 1); + struct libdivide_u64_branchfree_t ret = {tmp.magic, (uint8_t)(tmp.more & LIBDIVIDE_64_SHIFT_MASK)}; + return ret; +} + +uint64_t libdivide_u64_do(uint64_t numer, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return numer >> more; + } + else { + uint64_t q = libdivide_mullhi_u64(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + uint64_t t = ((numer - q) >> 1) + q; + return t >> (more & LIBDIVIDE_64_SHIFT_MASK); + } + else { + // All upper bits are 0, + // don't need to mask them off. + return q >> more; + } + } +} + +uint64_t libdivide_u64_branchfree_do(uint64_t numer, const struct libdivide_u64_branchfree_t *denom) { + uint64_t q = libdivide_mullhi_u64(denom->magic, numer); + uint64_t t = ((numer - q) >> 1) + q; + return t >> denom->more; +} + +uint64_t libdivide_u64_recover(const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { + return 1ULL << shift; + } else if (!(more & LIBDIVIDE_ADD_MARKER)) { + // We compute q = n/d = n*m / 2^(64 + shift) + // Therefore we have d = 2^(64 + shift) / m + // We need to ceil it. + // We know d is not a power of 2, so m is not a power of 2, + // so we can just add 1 to the floor + uint64_t hi_dividend = 1ULL << shift; + uint64_t rem_ignored; + return 1 + libdivide_128_div_64_to_64(hi_dividend, 0, denom->magic, &rem_ignored); + } else { + // Here we wish to compute d = 2^(64+shift+1)/(m+2^64). + // Notice (m + 2^64) is a 65 bit number. This gets hairy. See + // libdivide_u32_recover for more on what we do here. + // TODO: do something better than 128 bit math + + // Full n is a (potentially) 129 bit value + // half_n is a 128 bit value + // Compute the hi half of half_n. Low half is 0. + uint64_t half_n_hi = 1ULL << shift, half_n_lo = 0; + // d is a 65 bit value. The high bit is always set to 1. + const uint64_t d_hi = 1, d_lo = denom->magic; + // Note that the quotient is guaranteed <= 64 bits, + // but the remainder may need 65! + uint64_t r_hi, r_lo; + uint64_t half_q = libdivide_128_div_128_to_64(half_n_hi, half_n_lo, d_hi, d_lo, &r_hi, &r_lo); + // We computed 2^(64+shift)/(m+2^64) + // Double the remainder ('dr') and check if that is larger than d + // Note that d is a 65 bit value, so r1 is small and so r1 + r1 + // cannot overflow + uint64_t dr_lo = r_lo + r_lo; + uint64_t dr_hi = r_hi + r_hi + (dr_lo < r_lo); // last term is carry + int dr_exceeds_d = (dr_hi > d_hi) || (dr_hi == d_hi && dr_lo >= d_lo); + uint64_t full_q = half_q + half_q + (dr_exceeds_d ? 1 : 0); + return full_q + 1; + } +} + +uint64_t libdivide_u64_branchfree_recover(const struct libdivide_u64_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { + return 1ULL << (shift + 1); + } else { + // Here we wish to compute d = 2^(64+shift+1)/(m+2^64). + // Notice (m + 2^64) is a 65 bit number. This gets hairy. See + // libdivide_u32_recover for more on what we do here. + // TODO: do something better than 128 bit math + + // Full n is a (potentially) 129 bit value + // half_n is a 128 bit value + // Compute the hi half of half_n. Low half is 0. + uint64_t half_n_hi = 1ULL << shift, half_n_lo = 0; + // d is a 65 bit value. The high bit is always set to 1. + const uint64_t d_hi = 1, d_lo = denom->magic; + // Note that the quotient is guaranteed <= 64 bits, + // but the remainder may need 65! + uint64_t r_hi, r_lo; + uint64_t half_q = libdivide_128_div_128_to_64(half_n_hi, half_n_lo, d_hi, d_lo, &r_hi, &r_lo); + // We computed 2^(64+shift)/(m+2^64) + // Double the remainder ('dr') and check if that is larger than d + // Note that d is a 65 bit value, so r1 is small and so r1 + r1 + // cannot overflow + uint64_t dr_lo = r_lo + r_lo; + uint64_t dr_hi = r_hi + r_hi + (dr_lo < r_lo); // last term is carry + int dr_exceeds_d = (dr_hi > d_hi) || (dr_hi == d_hi && dr_lo >= d_lo); + uint64_t full_q = half_q + half_q + (dr_exceeds_d ? 1 : 0); + return full_q + 1; + } +}*/ + +/////////// SINT32 + +/*static inline struct libdivide_s32_t libdivide_internal_s32_gen(int32_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_s32_t result; + + // If d is a power of 2, or negative a power of 2, we have to use a shift. + // This is especially important because the magic algorithm fails for -1. + // To check if d is a power of 2 or its inverse, it suffices to check + // whether its absolute value has exactly one bit set. This works even for + // INT_MIN, because abs(INT_MIN) == INT_MIN, and INT_MIN has one bit set + // and is a power of 2. + uint32_t ud = (uint32_t)d; + uint32_t absD = (d < 0) ? -ud : ud; + uint32_t floor_log_2_d = 31 - libdivide_count_leading_zeros32(absD); + // check if exactly one bit is set, + // don't care if absD is 0 since that's divide by zero + if ((absD & (absD - 1)) == 0) { + // Branchfree and normal paths are exactly the same + result.magic = 0; + result.more = floor_log_2_d | (d < 0 ? LIBDIVIDE_NEGATIVE_DIVISOR : 0); + } else { + LIBDIVIDE_ASSERT(floor_log_2_d >= 1); + + uint8_t more; + // the dividend here is 2**(floor_log_2_d + 31), so the low 32 bit word + // is 0 and the high word is floor_log_2_d - 1 + uint32_t rem, proposed_m; + proposed_m = libdivide_64_div_32_to_32(1U << (floor_log_2_d - 1), 0, absD, &rem); + const uint32_t e = absD - rem; + + // We are going to start with a power of floor_log_2_d - 1. + // This works if works if e < 2**floor_log_2_d. + if (!branchfree && e < (1U << floor_log_2_d)) { + // This power works + more = floor_log_2_d - 1; + } else { + // We need to go one higher. This should not make proposed_m + // overflow, but it will make it negative when interpreted as an + // int32_t. + proposed_m += proposed_m; + const uint32_t twice_rem = rem + rem; + if (twice_rem >= absD || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + + proposed_m += 1; + int32_t magic = (int32_t)proposed_m; + + // Mark if we are negative. Note we only negate the magic number in the + // branchfull case. + if (d < 0) { + more |= LIBDIVIDE_NEGATIVE_DIVISOR; + if (!branchfree) { + magic = -magic; + } + } + + result.more = more; + result.magic = magic; + } + return result; +} + +struct libdivide_s32_t libdivide_s32_gen(int32_t d) { + return libdivide_internal_s32_gen(d, 0); +} + +struct libdivide_s32_branchfree_t libdivide_s32_branchfree_gen(int32_t d) { + struct libdivide_s32_t tmp = libdivide_internal_s32_gen(d, 1); + struct libdivide_s32_branchfree_t result = {tmp.magic, tmp.more}; + return result; +} + +int32_t libdivide_s32_do(int32_t numer, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + uint32_t sign = (int8_t)more >> 7; + uint32_t mask = (1U << shift) - 1; + uint32_t uq = numer + ((numer >> 31) & mask); + int32_t q = (int32_t)uq; + q >>= shift; + q = (q ^ sign) - sign; + return q; + } else { + uint32_t uq = (uint32_t)libdivide_mullhi_s32(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift and then sign extend + int32_t sign = (int8_t)more >> 7; + // q += (more < 0 ? -numer : numer) + // cast required to avoid UB + uq += ((uint32_t)numer ^ sign) - sign; + } + int32_t q = (int32_t)uq; + q >>= shift; + q += (q < 0); + return q; + } +} + +int32_t libdivide_s32_branchfree_do(int32_t numer, const struct libdivide_s32_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift and then sign extend + int32_t sign = (int8_t)more >> 7; + int32_t magic = denom->magic; + int32_t q = libdivide_mullhi_s32(magic, numer); + q += numer; + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is a power of + // 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + uint32_t q_sign = (uint32_t)(q >> 31); + q += q_sign & ((1U << shift) - is_power_of_2); + + // Now arithmetic right shift + q >>= shift; + // Negate if needed + q = (q ^ sign) - sign; + + return q; +} + +int32_t libdivide_s32_recover(const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + if (!denom->magic) { + uint32_t absD = 1U << shift; + if (more & LIBDIVIDE_NEGATIVE_DIVISOR) { + absD = -absD; + } + return (int32_t)absD; + } else { + // Unsigned math is much easier + // We negate the magic number only in the branchfull case, and we don't + // know which case we're in. However we have enough information to + // determine the correct sign of the magic number. The divisor was + // negative if LIBDIVIDE_NEGATIVE_DIVISOR is set. If ADD_MARKER is set, + // the magic number's sign is opposite that of the divisor. + // We want to compute the positive magic number. + int negative_divisor = (more & LIBDIVIDE_NEGATIVE_DIVISOR); + int magic_was_negated = (more & LIBDIVIDE_ADD_MARKER) + ? denom->magic > 0 : denom->magic < 0; + + // Handle the power of 2 case (including branchfree) + if (denom->magic == 0) { + int32_t result = 1U << shift; + return negative_divisor ? -result : result; + } + + uint32_t d = (uint32_t)(magic_was_negated ? -denom->magic : denom->magic); + uint64_t n = 1ULL << (32 + shift); // this shift cannot exceed 30 + uint32_t q = (uint32_t)(n / d); + int32_t result = (int32_t)q; + result += 1; + return negative_divisor ? -result : result; + } +} + +int32_t libdivide_s32_branchfree_recover(const struct libdivide_s32_branchfree_t *denom) { + return libdivide_s32_recover((const struct libdivide_s32_t *)denom); +}*/ + +///////////// SINT64 + +/*static inline struct libdivide_s64_t libdivide_internal_s64_gen(int64_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_s64_t result; + + // If d is a power of 2, or negative a power of 2, we have to use a shift. + // This is especially important because the magic algorithm fails for -1. + // To check if d is a power of 2 or its inverse, it suffices to check + // whether its absolute value has exactly one bit set. This works even for + // INT_MIN, because abs(INT_MIN) == INT_MIN, and INT_MIN has one bit set + // and is a power of 2. + uint64_t ud = (uint64_t)d; + uint64_t absD = (d < 0) ? -ud : ud; + uint32_t floor_log_2_d = 63 - libdivide_count_leading_zeros64(absD); + // check if exactly one bit is set, + // don't care if absD is 0 since that's divide by zero + if ((absD & (absD - 1)) == 0) { + // Branchfree and non-branchfree cases are the same + result.magic = 0; + result.more = floor_log_2_d | (d < 0 ? LIBDIVIDE_NEGATIVE_DIVISOR : 0); + } else { + // the dividend here is 2**(floor_log_2_d + 63), so the low 64 bit word + // is 0 and the high word is floor_log_2_d - 1 + uint8_t more; + uint64_t rem, proposed_m; + proposed_m = libdivide_128_div_64_to_64(1ULL << (floor_log_2_d - 1), 0, absD, &rem); + const uint64_t e = absD - rem; + + // We are going to start with a power of floor_log_2_d - 1. + // This works if works if e < 2**floor_log_2_d. + if (!branchfree && e < (1ULL << floor_log_2_d)) { + // This power works + more = floor_log_2_d - 1; + } else { + // We need to go one higher. This should not make proposed_m + // overflow, but it will make it negative when interpreted as an + // int32_t. + proposed_m += proposed_m; + const uint64_t twice_rem = rem + rem; + if (twice_rem >= absD || twice_rem < rem) proposed_m += 1; + // note that we only set the LIBDIVIDE_NEGATIVE_DIVISOR bit if we + // also set ADD_MARKER this is an annoying optimization that + // enables algorithm #4 to avoid the mask. However we always set it + // in the branchfree case + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + proposed_m += 1; + int64_t magic = (int64_t)proposed_m; + + // Mark if we are negative + if (d < 0) { + more |= LIBDIVIDE_NEGATIVE_DIVISOR; + if (!branchfree) { + magic = -magic; + } + } + + result.more = more; + result.magic = magic; + } + return result; +} + +struct libdivide_s64_t libdivide_s64_gen(int64_t d) { + return libdivide_internal_s64_gen(d, 0); +} + +struct libdivide_s64_branchfree_t libdivide_s64_branchfree_gen(int64_t d) { + struct libdivide_s64_t tmp = libdivide_internal_s64_gen(d, 1); + struct libdivide_s64_branchfree_t ret = {tmp.magic, tmp.more}; + return ret; +} + +int64_t libdivide_s64_do(int64_t numer, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { // shift path + uint64_t mask = (1ULL << shift) - 1; + uint64_t uq = numer + ((numer >> 63) & mask); + int64_t q = (int64_t)uq; + q >>= shift; + // must be arithmetic shift and then sign-extend + int64_t sign = (int8_t)more >> 7; + q = (q ^ sign) - sign; + return q; + } else { + uint64_t uq = (uint64_t)libdivide_mullhi_s64(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift and then sign extend + int64_t sign = (int8_t)more >> 7; + // q += (more < 0 ? -numer : numer) + // cast required to avoid UB + uq += ((uint64_t)numer ^ sign) - sign; + } + int64_t q = (int64_t)uq; + q >>= shift; + q += (q < 0); + return q; + } +} + +int64_t libdivide_s64_branchfree_do(int64_t numer, const struct libdivide_s64_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift and then sign extend + int64_t sign = (int8_t)more >> 7; + int64_t magic = denom->magic; + int64_t q = libdivide_mullhi_s64(magic, numer); + q += numer; + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is a power of + // 2, or (2**shift) if it is not a power of 2. + uint64_t is_power_of_2 = (magic == 0); + uint64_t q_sign = (uint64_t)(q >> 63); + q += q_sign & ((1ULL << shift) - is_power_of_2); + + // Arithmetic right shift + q >>= shift; + // Negate if needed + q = (q ^ sign) - sign; + + return q; +} + +int64_t libdivide_s64_recover(const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + if (denom->magic == 0) { // shift path + uint64_t absD = 1ULL << shift; + if (more & LIBDIVIDE_NEGATIVE_DIVISOR) { + absD = -absD; + } + return (int64_t)absD; + } else { + // Unsigned math is much easier + int negative_divisor = (more & LIBDIVIDE_NEGATIVE_DIVISOR); + int magic_was_negated = (more & LIBDIVIDE_ADD_MARKER) + ? denom->magic > 0 : denom->magic < 0; + + uint64_t d = (uint64_t)(magic_was_negated ? -denom->magic : denom->magic); + uint64_t n_hi = 1ULL << shift, n_lo = 0; + uint64_t rem_ignored; + uint64_t q = libdivide_128_div_64_to_64(n_hi, n_lo, d, &rem_ignored); + int64_t result = (int64_t)(q + 1); + if (negative_divisor) { + result = -result; + } + return result; + } +} + +int64_t libdivide_s64_branchfree_recover(const struct libdivide_s64_branchfree_t *denom) { + return libdivide_s64_recover((const struct libdivide_s64_t *)denom); +}*/ + +#if defined(LIBDIVIDE_AVX512) + +static inline __m512i libdivide_u32_do_vector(__m512i numers, const struct libdivide_u32_t *denom); +static inline __m512i libdivide_s32_do_vector(__m512i numers, const struct libdivide_s32_t *denom); +static inline __m512i libdivide_u64_do_vector(__m512i numers, const struct libdivide_u64_t *denom); +static inline __m512i libdivide_s64_do_vector(__m512i numers, const struct libdivide_s64_t *denom); + +static inline __m512i libdivide_u32_branchfree_do_vector(__m512i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m512i libdivide_s32_branchfree_do_vector(__m512i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m512i libdivide_u64_branchfree_do_vector(__m512i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m512i libdivide_s64_branchfree_do_vector(__m512i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +static inline __m512i libdivide_s64_signbits(__m512i v) {; + return _mm512_srai_epi64(v, 63); +} + +static inline __m512i libdivide_s64_shift_right_vector(__m512i v, int amt) { + return _mm512_srai_epi64(v, amt); +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m512i libdivide_mullhi_u32_vector(__m512i a, __m512i b) { + __m512i hi_product_0Z2Z = _mm512_srli_epi64(_mm512_mul_epu32(a, b), 32); + __m512i a1X3X = _mm512_srli_epi64(a, 32); + __m512i mask = _mm512_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0); + __m512i hi_product_Z1Z3 = _mm512_and_si512(_mm512_mul_epu32(a1X3X, b), mask); + return _mm512_or_si512(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// b is one 32-bit value repeated. +static inline __m512i libdivide_mullhi_s32_vector(__m512i a, __m512i b) { + __m512i hi_product_0Z2Z = _mm512_srli_epi64(_mm512_mul_epi32(a, b), 32); + __m512i a1X3X = _mm512_srli_epi64(a, 32); + __m512i mask = _mm512_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0); + __m512i hi_product_Z1Z3 = _mm512_and_si512(_mm512_mul_epi32(a1X3X, b), mask); + return _mm512_or_si512(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m512i libdivide_mullhi_u64_vector(__m512i x, __m512i y) { + __m512i lomask = _mm512_set1_epi64(0xffffffff); + __m512i xh = _mm512_shuffle_epi32(x, (_MM_PERM_ENUM) 0xB1); + __m512i yh = _mm512_shuffle_epi32(y, (_MM_PERM_ENUM) 0xB1); + __m512i w0 = _mm512_mul_epu32(x, y); + __m512i w1 = _mm512_mul_epu32(x, yh); + __m512i w2 = _mm512_mul_epu32(xh, y); + __m512i w3 = _mm512_mul_epu32(xh, yh); + __m512i w0h = _mm512_srli_epi64(w0, 32); + __m512i s1 = _mm512_add_epi64(w1, w0h); + __m512i s1l = _mm512_and_si512(s1, lomask); + __m512i s1h = _mm512_srli_epi64(s1, 32); + __m512i s2 = _mm512_add_epi64(w2, s1l); + __m512i s2h = _mm512_srli_epi64(s2, 32); + __m512i hi = _mm512_add_epi64(w3, s1h); + hi = _mm512_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m512i libdivide_mullhi_s64_vector(__m512i x, __m512i y) { + __m512i p = libdivide_mullhi_u64_vector(x, y); + __m512i t1 = _mm512_and_si512(libdivide_s64_signbits(x), y); + __m512i t2 = _mm512_and_si512(libdivide_s64_signbits(y), x); + p = _mm512_sub_epi64(p, t1); + p = _mm512_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m512i libdivide_u32_do_vector(__m512i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm512_srli_epi32(numers, more); + } + else { + __m512i q = libdivide_mullhi_u32_vector(numers, _mm512_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m512i t = _mm512_add_epi32(_mm512_srli_epi32(_mm512_sub_epi32(numers, q), 1), q); + return _mm512_srli_epi32(t, shift); + } + else { + return _mm512_srli_epi32(q, more); + } + } +} + +__m512i libdivide_u32_branchfree_do_vector(__m512i numers, const struct libdivide_u32_branchfree_t *denom) { + __m512i q = libdivide_mullhi_u32_vector(numers, _mm512_set1_epi32(denom->magic)); + __m512i t = _mm512_add_epi32(_mm512_srli_epi32(_mm512_sub_epi32(numers, q), 1), q); + return _mm512_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m512i libdivide_u64_do_vector(__m512i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm512_srli_epi64(numers, more); + } + else { + __m512i q = libdivide_mullhi_u64_vector(numers, _mm512_set1_epi64(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m512i t = _mm512_add_epi64(_mm512_srli_epi64(_mm512_sub_epi64(numers, q), 1), q); + return _mm512_srli_epi64(t, shift); + } + else { + return _mm512_srli_epi64(q, more); + } + } +} + +__m512i libdivide_u64_branchfree_do_vector(__m512i numers, const struct libdivide_u64_branchfree_t *denom) { + __m512i q = libdivide_mullhi_u64_vector(numers, _mm512_set1_epi64(denom->magic)); + __m512i t = _mm512_add_epi64(_mm512_srli_epi64(_mm512_sub_epi64(numers, q), 1), q); + return _mm512_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m512i libdivide_s32_do_vector(__m512i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m512i roundToZeroTweak = _mm512_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m512i q = _mm512_add_epi32(numers, _mm512_and_si512(_mm512_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm512_srai_epi32(q, shift); + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm512_sub_epi32(_mm512_xor_si512(q, sign), sign); + return q; + } + else { + __m512i q = libdivide_mullhi_s32_vector(numers, _mm512_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm512_add_epi32(q, _mm512_sub_epi32(_mm512_xor_si512(numers, sign), sign)); + } + // q >>= shift + q = _mm512_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm512_add_epi32(q, _mm512_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m512i libdivide_s32_branchfree_do_vector(__m512i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + __m512i q = libdivide_mullhi_s32_vector(numers, _mm512_set1_epi32(magic)); + q = _mm512_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m512i q_sign = _mm512_srai_epi32(q, 31); // q_sign = q >> 31 + __m512i mask = _mm512_set1_epi32((1U << shift) - is_power_of_2); + q = _mm512_add_epi32(q, _mm512_and_si512(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm512_srai_epi32(q, shift); // q >>= shift + q = _mm512_sub_epi32(_mm512_xor_si512(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m512i libdivide_s64_do_vector(__m512i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m512i roundToZeroTweak = _mm512_set1_epi64(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m512i q = _mm512_add_epi64(numers, _mm512_and_si512(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm512_sub_epi64(_mm512_xor_si512(q, sign), sign); + return q; + } + else { + __m512i q = libdivide_mullhi_s64_vector(numers, _mm512_set1_epi64(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm512_add_epi64(q, _mm512_sub_epi64(_mm512_xor_si512(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm512_add_epi64(q, _mm512_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m512i libdivide_s64_branchfree_do_vector(__m512i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m512i q = libdivide_mullhi_s64_vector(numers, _mm512_set1_epi64(magic)); + q = _mm512_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m512i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m512i mask = _mm512_set1_epi64((1ULL << shift) - is_power_of_2); + q = _mm512_add_epi64(q, _mm512_and_si512(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm512_sub_epi64(_mm512_xor_si512(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#elif defined(LIBDIVIDE_AVX2) + +static inline __m256i libdivide_u32_do_vector(__m256i numers, const struct libdivide_u32_t *denom); +static inline __m256i libdivide_s32_do_vector(__m256i numers, const struct libdivide_s32_t *denom); +static inline __m256i libdivide_u64_do_vector(__m256i numers, const struct libdivide_u64_t *denom); +static inline __m256i libdivide_s64_do_vector(__m256i numers, const struct libdivide_s64_t *denom); + +static inline __m256i libdivide_u32_branchfree_do_vector(__m256i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m256i libdivide_s32_branchfree_do_vector(__m256i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m256i libdivide_u64_branchfree_do_vector(__m256i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m256i libdivide_s64_branchfree_do_vector(__m256i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +// Implementation of _mm256_srai_epi64(v, 63) (from AVX512). +static inline __m256i libdivide_s64_signbits(__m256i v) { + __m256i hiBitsDuped = _mm256_shuffle_epi32(v, _MM_SHUFFLE(3, 3, 1, 1)); + __m256i signBits = _mm256_srai_epi32(hiBitsDuped, 31); + return signBits; +} + +// Implementation of _mm256_srai_epi64 (from AVX512). +static inline __m256i libdivide_s64_shift_right_vector(__m256i v, int amt) { + const int b = 64 - amt; + __m256i m = _mm256_set1_epi64x(1ULL << (b - 1)); + __m256i x = _mm256_srli_epi64(v, amt); + __m256i result = _mm256_sub_epi64(_mm256_xor_si256(x, m), m); + return result; +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m256i libdivide_mullhi_u32_vector(__m256i a, __m256i b) { + __m256i hi_product_0Z2Z = _mm256_srli_epi64(_mm256_mul_epu32(a, b), 32); + __m256i a1X3X = _mm256_srli_epi64(a, 32); + __m256i mask = _mm256_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0); + __m256i hi_product_Z1Z3 = _mm256_and_si256(_mm256_mul_epu32(a1X3X, b), mask); + return _mm256_or_si256(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// b is one 32-bit value repeated. +static inline __m256i libdivide_mullhi_s32_vector(__m256i a, __m256i b) { + __m256i hi_product_0Z2Z = _mm256_srli_epi64(_mm256_mul_epi32(a, b), 32); + __m256i a1X3X = _mm256_srli_epi64(a, 32); + __m256i mask = _mm256_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0); + __m256i hi_product_Z1Z3 = _mm256_and_si256(_mm256_mul_epi32(a1X3X, b), mask); + return _mm256_or_si256(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m256i libdivide_mullhi_u64_vector(__m256i x, __m256i y) { + __m256i lomask = _mm256_set1_epi64x(0xffffffff); + __m256i xh = _mm256_shuffle_epi32(x, 0xB1); // x0l, x0h, x1l, x1h + __m256i yh = _mm256_shuffle_epi32(y, 0xB1); // y0l, y0h, y1l, y1h + __m256i w0 = _mm256_mul_epu32(x, y); // x0l*y0l, x1l*y1l + __m256i w1 = _mm256_mul_epu32(x, yh); // x0l*y0h, x1l*y1h + __m256i w2 = _mm256_mul_epu32(xh, y); // x0h*y0l, x1h*y0l + __m256i w3 = _mm256_mul_epu32(xh, yh); // x0h*y0h, x1h*y1h + __m256i w0h = _mm256_srli_epi64(w0, 32); + __m256i s1 = _mm256_add_epi64(w1, w0h); + __m256i s1l = _mm256_and_si256(s1, lomask); + __m256i s1h = _mm256_srli_epi64(s1, 32); + __m256i s2 = _mm256_add_epi64(w2, s1l); + __m256i s2h = _mm256_srli_epi64(s2, 32); + __m256i hi = _mm256_add_epi64(w3, s1h); + hi = _mm256_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m256i libdivide_mullhi_s64_vector(__m256i x, __m256i y) { + __m256i p = libdivide_mullhi_u64_vector(x, y); + __m256i t1 = _mm256_and_si256(libdivide_s64_signbits(x), y); + __m256i t2 = _mm256_and_si256(libdivide_s64_signbits(y), x); + p = _mm256_sub_epi64(p, t1); + p = _mm256_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m256i libdivide_u32_do_vector(__m256i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm256_srli_epi32(numers, more); + } + else { + __m256i q = libdivide_mullhi_u32_vector(numers, _mm256_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m256i t = _mm256_add_epi32(_mm256_srli_epi32(_mm256_sub_epi32(numers, q), 1), q); + return _mm256_srli_epi32(t, shift); + } + else { + return _mm256_srli_epi32(q, more); + } + } +} + +__m256i libdivide_u32_branchfree_do_vector(__m256i numers, const struct libdivide_u32_branchfree_t *denom) { + __m256i q = libdivide_mullhi_u32_vector(numers, _mm256_set1_epi32(denom->magic)); + __m256i t = _mm256_add_epi32(_mm256_srli_epi32(_mm256_sub_epi32(numers, q), 1), q); + return _mm256_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m256i libdivide_u64_do_vector(__m256i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm256_srli_epi64(numers, more); + } + else { + __m256i q = libdivide_mullhi_u64_vector(numers, _mm256_set1_epi64x(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m256i t = _mm256_add_epi64(_mm256_srli_epi64(_mm256_sub_epi64(numers, q), 1), q); + return _mm256_srli_epi64(t, shift); + } + else { + return _mm256_srli_epi64(q, more); + } + } +} + +__m256i libdivide_u64_branchfree_do_vector(__m256i numers, const struct libdivide_u64_branchfree_t *denom) { + __m256i q = libdivide_mullhi_u64_vector(numers, _mm256_set1_epi64x(denom->magic)); + __m256i t = _mm256_add_epi64(_mm256_srli_epi64(_mm256_sub_epi64(numers, q), 1), q); + return _mm256_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m256i libdivide_s32_do_vector(__m256i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m256i roundToZeroTweak = _mm256_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m256i q = _mm256_add_epi32(numers, _mm256_and_si256(_mm256_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm256_srai_epi32(q, shift); + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm256_sub_epi32(_mm256_xor_si256(q, sign), sign); + return q; + } + else { + __m256i q = libdivide_mullhi_s32_vector(numers, _mm256_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm256_add_epi32(q, _mm256_sub_epi32(_mm256_xor_si256(numers, sign), sign)); + } + // q >>= shift + q = _mm256_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm256_add_epi32(q, _mm256_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m256i libdivide_s32_branchfree_do_vector(__m256i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + __m256i q = libdivide_mullhi_s32_vector(numers, _mm256_set1_epi32(magic)); + q = _mm256_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m256i q_sign = _mm256_srai_epi32(q, 31); // q_sign = q >> 31 + __m256i mask = _mm256_set1_epi32((1U << shift) - is_power_of_2); + q = _mm256_add_epi32(q, _mm256_and_si256(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm256_srai_epi32(q, shift); // q >>= shift + q = _mm256_sub_epi32(_mm256_xor_si256(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m256i libdivide_s64_do_vector(__m256i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m256i roundToZeroTweak = _mm256_set1_epi64x(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m256i q = _mm256_add_epi64(numers, _mm256_and_si256(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm256_sub_epi64(_mm256_xor_si256(q, sign), sign); + return q; + } + else { + __m256i q = libdivide_mullhi_s64_vector(numers, _mm256_set1_epi64x(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm256_add_epi64(q, _mm256_sub_epi64(_mm256_xor_si256(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm256_add_epi64(q, _mm256_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m256i libdivide_s64_branchfree_do_vector(__m256i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m256i q = libdivide_mullhi_s64_vector(numers, _mm256_set1_epi64x(magic)); + q = _mm256_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m256i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m256i mask = _mm256_set1_epi64x((1ULL << shift) - is_power_of_2); + q = _mm256_add_epi64(q, _mm256_and_si256(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm256_sub_epi64(_mm256_xor_si256(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#elif defined(LIBDIVIDE_SSE2) + +static inline __m128i libdivide_u32_do_vector(__m128i numers, const struct libdivide_u32_t *denom); +static inline __m128i libdivide_s32_do_vector(__m128i numers, const struct libdivide_s32_t *denom); +static inline __m128i libdivide_u64_do_vector(__m128i numers, const struct libdivide_u64_t *denom); +static inline __m128i libdivide_s64_do_vector(__m128i numers, const struct libdivide_s64_t *denom); + +static inline __m128i libdivide_u32_branchfree_do_vector(__m128i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m128i libdivide_s32_branchfree_do_vector(__m128i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m128i libdivide_u64_branchfree_do_vector(__m128i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m128i libdivide_s64_branchfree_do_vector(__m128i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +// Implementation of _mm_srai_epi64(v, 63) (from AVX512). +static inline __m128i libdivide_s64_signbits(__m128i v) { + __m128i hiBitsDuped = _mm_shuffle_epi32(v, _MM_SHUFFLE(3, 3, 1, 1)); + __m128i signBits = _mm_srai_epi32(hiBitsDuped, 31); + return signBits; +} + +// Implementation of _mm_srai_epi64 (from AVX512). +static inline __m128i libdivide_s64_shift_right_vector(__m128i v, int amt) { + const int b = 64 - amt; + __m128i m = _mm_set1_epi64x(1ULL << (b - 1)); + __m128i x = _mm_srli_epi64(v, amt); + __m128i result = _mm_sub_epi64(_mm_xor_si128(x, m), m); + return result; +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m128i libdivide_mullhi_u32_vector(__m128i a, __m128i b) { + __m128i hi_product_0Z2Z = _mm_srli_epi64(_mm_mul_epu32(a, b), 32); + __m128i a1X3X = _mm_srli_epi64(a, 32); + __m128i mask = _mm_set_epi32(-1, 0, -1, 0); + __m128i hi_product_Z1Z3 = _mm_and_si128(_mm_mul_epu32(a1X3X, b), mask); + return _mm_or_si128(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// SSE2 does not have a signed multiplication instruction, but we can convert +// unsigned to signed pretty efficiently. Again, b is just a 32 bit value +// repeated four times. +static inline __m128i libdivide_mullhi_s32_vector(__m128i a, __m128i b) { + __m128i p = libdivide_mullhi_u32_vector(a, b); + // t1 = (a >> 31) & y, arithmetic shift + __m128i t1 = _mm_and_si128(_mm_srai_epi32(a, 31), b); + __m128i t2 = _mm_and_si128(_mm_srai_epi32(b, 31), a); + p = _mm_sub_epi32(p, t1); + p = _mm_sub_epi32(p, t2); + return p; +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m128i libdivide_mullhi_u64_vector(__m128i x, __m128i y) { + __m128i lomask = _mm_set1_epi64x(0xffffffff); + __m128i xh = _mm_shuffle_epi32(x, 0xB1); // x0l, x0h, x1l, x1h + __m128i yh = _mm_shuffle_epi32(y, 0xB1); // y0l, y0h, y1l, y1h + __m128i w0 = _mm_mul_epu32(x, y); // x0l*y0l, x1l*y1l + __m128i w1 = _mm_mul_epu32(x, yh); // x0l*y0h, x1l*y1h + __m128i w2 = _mm_mul_epu32(xh, y); // x0h*y0l, x1h*y0l + __m128i w3 = _mm_mul_epu32(xh, yh); // x0h*y0h, x1h*y1h + __m128i w0h = _mm_srli_epi64(w0, 32); + __m128i s1 = _mm_add_epi64(w1, w0h); + __m128i s1l = _mm_and_si128(s1, lomask); + __m128i s1h = _mm_srli_epi64(s1, 32); + __m128i s2 = _mm_add_epi64(w2, s1l); + __m128i s2h = _mm_srli_epi64(s2, 32); + __m128i hi = _mm_add_epi64(w3, s1h); + hi = _mm_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m128i libdivide_mullhi_s64_vector(__m128i x, __m128i y) { + __m128i p = libdivide_mullhi_u64_vector(x, y); + __m128i t1 = _mm_and_si128(libdivide_s64_signbits(x), y); + __m128i t2 = _mm_and_si128(libdivide_s64_signbits(y), x); + p = _mm_sub_epi64(p, t1); + p = _mm_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m128i libdivide_u32_do_vector(__m128i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm_srli_epi32(numers, more); + } + else { + __m128i q = libdivide_mullhi_u32_vector(numers, _mm_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m128i t = _mm_add_epi32(_mm_srli_epi32(_mm_sub_epi32(numers, q), 1), q); + return _mm_srli_epi32(t, shift); + } + else { + return _mm_srli_epi32(q, more); + } + } +} + +__m128i libdivide_u32_branchfree_do_vector(__m128i numers, const struct libdivide_u32_branchfree_t *denom) { + __m128i q = libdivide_mullhi_u32_vector(numers, _mm_set1_epi32(denom->magic)); + __m128i t = _mm_add_epi32(_mm_srli_epi32(_mm_sub_epi32(numers, q), 1), q); + return _mm_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m128i libdivide_u64_do_vector(__m128i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm_srli_epi64(numers, more); + } + else { + __m128i q = libdivide_mullhi_u64_vector(numers, _mm_set1_epi64x(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m128i t = _mm_add_epi64(_mm_srli_epi64(_mm_sub_epi64(numers, q), 1), q); + return _mm_srli_epi64(t, shift); + } + else { + return _mm_srli_epi64(q, more); + } + } +} + +__m128i libdivide_u64_branchfree_do_vector(__m128i numers, const struct libdivide_u64_branchfree_t *denom) { + __m128i q = libdivide_mullhi_u64_vector(numers, _mm_set1_epi64x(denom->magic)); + __m128i t = _mm_add_epi64(_mm_srli_epi64(_mm_sub_epi64(numers, q), 1), q); + return _mm_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m128i libdivide_s32_do_vector(__m128i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m128i roundToZeroTweak = _mm_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m128i q = _mm_add_epi32(numers, _mm_and_si128(_mm_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm_srai_epi32(q, shift); + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm_sub_epi32(_mm_xor_si128(q, sign), sign); + return q; + } + else { + __m128i q = libdivide_mullhi_s32_vector(numers, _mm_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm_add_epi32(q, _mm_sub_epi32(_mm_xor_si128(numers, sign), sign)); + } + // q >>= shift + q = _mm_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm_add_epi32(q, _mm_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m128i libdivide_s32_branchfree_do_vector(__m128i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + __m128i q = libdivide_mullhi_s32_vector(numers, _mm_set1_epi32(magic)); + q = _mm_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m128i q_sign = _mm_srai_epi32(q, 31); // q_sign = q >> 31 + __m128i mask = _mm_set1_epi32((1U << shift) - is_power_of_2); + q = _mm_add_epi32(q, _mm_and_si128(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm_srai_epi32(q, shift); // q >>= shift + q = _mm_sub_epi32(_mm_xor_si128(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m128i libdivide_s64_do_vector(__m128i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m128i roundToZeroTweak = _mm_set1_epi64x(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m128i q = _mm_add_epi64(numers, _mm_and_si128(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm_sub_epi64(_mm_xor_si128(q, sign), sign); + return q; + } + else { + __m128i q = libdivide_mullhi_s64_vector(numers, _mm_set1_epi64x(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm_add_epi64(q, _mm_sub_epi64(_mm_xor_si128(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm_add_epi64(q, _mm_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m128i libdivide_s64_branchfree_do_vector(__m128i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m128i q = libdivide_mullhi_s64_vector(numers, _mm_set1_epi64x(magic)); + q = _mm_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m128i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m128i mask = _mm_set1_epi64x((1ULL << shift) - is_power_of_2); + q = _mm_add_epi64(q, _mm_and_si128(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm_sub_epi64(_mm_xor_si128(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#endif + +/////////// C++ stuff + +#ifdef __cplusplus + +// The C++ divider class is templated on both an integer type +// (like uint64_t) and an algorithm type. +// * BRANCHFULL is the default algorithm type. +// * BRANCHFREE is the branchfree algorithm type. +enum { + BRANCHFULL, + BRANCHFREE +}; + +#if defined(LIBDIVIDE_AVX512) + #define LIBDIVIDE_VECTOR_TYPE __m512i +#elif defined(LIBDIVIDE_AVX2) + #define LIBDIVIDE_VECTOR_TYPE __m256i +#elif defined(LIBDIVIDE_SSE2) + #define LIBDIVIDE_VECTOR_TYPE __m128i +#endif + +#if !defined(LIBDIVIDE_VECTOR_TYPE) + #define LIBDIVIDE_DIVIDE_VECTOR(ALGO) +#else + #define LIBDIVIDE_DIVIDE_VECTOR(ALGO) \ + LIBDIVIDE_VECTOR_TYPE divide(LIBDIVIDE_VECTOR_TYPE n) const { \ + return libdivide_##ALGO##_do_vector(n, &denom); \ + } +#endif + +// The DISPATCHER_GEN() macro generates C++ methods (for the given integer +// and algorithm types) that redirect to libdivide's C API. +#define DISPATCHER_GEN(T, ALGO) \ + libdivide_##ALGO##_t denom; \ + dispatcher() { } \ + dispatcher(T d) \ + : denom(libdivide_##ALGO##_gen(d)) \ + { } \ + T divide(T n) const { \ + return libdivide_##ALGO##_do(n, &denom); \ + } \ + LIBDIVIDE_DIVIDE_VECTOR(ALGO) \ + T recover() const { \ + return libdivide_##ALGO##_recover(&denom); \ + } + +// The dispatcher selects a specific division algorithm for a given +// type and ALGO using partial template specialization. +template struct dispatcher { }; + +template<> struct dispatcher { DISPATCHER_GEN(int32_t, s32) }; +template<> struct dispatcher { DISPATCHER_GEN(int32_t, s32_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(uint32_t, u32) }; +template<> struct dispatcher { DISPATCHER_GEN(uint32_t, u32_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(int64_t, s64) }; +template<> struct dispatcher { DISPATCHER_GEN(int64_t, s64_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(uint64_t, u64) }; +template<> struct dispatcher { DISPATCHER_GEN(uint64_t, u64_branchfree) }; + +// This is the main divider class for use by the user (C++ API). +// The actual division algorithm is selected using the dispatcher struct +// based on the integer and algorithm template parameters. +template +class divider { +public: + // We leave the default constructor empty so that creating + // an array of dividers and then initializing them + // later doesn't slow us down. + divider() { } + + // Constructor that takes the divisor as a parameter + divider(T d) : div(d) { } + + // Divides n by the divisor + T divide(T n) const { + return div.divide(n); + } + + // Recovers the divisor, returns the value that was + // used to initialize this divider object. + T recover() const { + return div.recover(); + } + + bool operator==(const divider& other) const { + return div.denom.magic == other.denom.magic && + div.denom.more == other.denom.more; + } + + bool operator!=(const divider& other) const { + return !(*this == other); + } + +#if defined(LIBDIVIDE_VECTOR_TYPE) + // Treats the vector as packed integer values with the same type as + // the divider (e.g. s32, u32, s64, u64) and divides each of + // them by the divider, returning the packed quotients. + LIBDIVIDE_VECTOR_TYPE divide(LIBDIVIDE_VECTOR_TYPE n) const { + return div.divide(n); + } +#endif + +private: + // Storage for the actual divisor + dispatcher::value, + std::is_signed::value, sizeof(T), ALGO> div; +}; + +// Overload of operator / for scalar division +template +T operator/(T n, const divider& div) { + return div.divide(n); +} + +// Overload of operator /= for scalar division +template +T& operator/=(T& n, const divider& div) { + n = div.divide(n); + return n; +} + +#if defined(LIBDIVIDE_VECTOR_TYPE) + // Overload of operator / for vector division + template + LIBDIVIDE_VECTOR_TYPE operator/(LIBDIVIDE_VECTOR_TYPE n, const divider& div) { + return div.divide(n); + } + // Overload of operator /= for vector division + template + LIBDIVIDE_VECTOR_TYPE& operator/=(LIBDIVIDE_VECTOR_TYPE& n, const divider& div) { + n = div.divide(n); + return n; + } +#endif + +// libdivdie::branchfree_divider +template +using branchfree_divider = divider; + +} // namespace libdivide + +#endif // __cplusplus + +#endif // LIBDIVIDE_H diff --git a/src/locale/en.po b/src/locale/en.po index 30ebe4368..8dd08173d 100644 --- a/src/locale/en.po +++ b/src/locale/en.po @@ -466,7 +466,7 @@ msgid "" msgstr "" #: d_clisrv.c:1764 -msgid "has been kicked (Go away)\n" +msgid "has been kicked (No reason given)\n" msgstr "" #: d_clisrv.c:1768 @@ -474,7 +474,7 @@ msgid "left the game (Broke ping limit)\n" msgstr "" #: d_clisrv.c:1772 -msgid "left the game (Consistency failure)\n" +msgid "left the game (Synch failure)\n" msgstr "" #: d_clisrv.c:1778 @@ -501,7 +501,7 @@ msgid "left the game\n" msgstr "" #: d_clisrv.c:1798 -msgid "has been banned (Don't come back)\n" +msgid "has been banned (No reason given)\n" msgstr "" #: d_clisrv.c:1802 diff --git a/src/locale/srb2.pot b/src/locale/srb2.pot index 960c36dbe..cd2db750d 100644 --- a/src/locale/srb2.pot +++ b/src/locale/srb2.pot @@ -459,7 +459,7 @@ msgid "" msgstr "" #: d_clisrv.c:1889 -msgid "has been kicked (Go away)\n" +msgid "has been kicked (No reason given)\n" msgstr "" #: d_clisrv.c:1893 @@ -467,7 +467,7 @@ msgid "left the game (Broke ping limit)\n" msgstr "" #: d_clisrv.c:1897 -msgid "left the game (Consistency failure)\n" +msgid "left the game (Synch failure)\n" msgstr "" #: d_clisrv.c:1903 @@ -494,7 +494,7 @@ msgid "left the game\n" msgstr "" #: d_clisrv.c:1923 -msgid "has been banned (Don't come back)\n" +msgid "has been banned (No reason given)\n" msgstr "" #: d_clisrv.c:1927 diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 916fa9254..d6f40846c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,6 +28,7 @@ #include "console.h" #include "d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff +#include "m_misc.h" // M_MapNumber #include "lua_script.h" #include "lua_libs.h" @@ -212,6 +213,8 @@ static const struct { {META_ACTION, "action"}, {META_LUABANKS, "luabanks[]"}, + + {META_MOUSE, "mouse_t"}, {NULL, NULL} }; @@ -242,16 +245,10 @@ static const char *GetUserdataUType(lua_State *L) // or players[0].powers -> "player_t.powers" static int lib_userdataType(lua_State *L) { - int type; lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more) - type = lua_type(L, 1); - if (type == LUA_TLIGHTUSERDATA || type == LUA_TUSERDATA) - { - lua_pushstring(L, GetUserdataUType(L)); - return 1; - } - else - return luaL_typerror(L, 1, "userdata"); + luaL_checktype(L, 1, LUA_TUSERDATA); + lua_pushstring(L, GetUserdataUType(L)); + return 1; } // Takes a metatable as first and only argument @@ -363,6 +360,23 @@ static int lib_pGetColorAfter(lua_State *L) return 1; } +// M_MISC +////////////// + +static int lib_mMapNumber(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + size_t len = strlen(arg); + if (len == 2 || len == 5) { + char first = arg[len-2]; + char second = arg[len-1]; + lua_pushinteger(L, M_MapNumber(first, second)); + } else { + lua_pushinteger(L, 0); + } + return 1; +} + // M_RANDOM ////////////// @@ -432,7 +446,7 @@ static int lib_pAproxDistance(lua_State *L) fixed_t dx = luaL_checkfixed(L, 1); fixed_t dy = luaL_checkfixed(L, 2); //HUDSAFE - lua_pushfixed(L, R_PointToDist2(0, 0, dx, dy)); + lua_pushfixed(L, P_AproxDistance(dx, dy)); return 1; } @@ -1050,48 +1064,56 @@ static int lib_pSceneryXYMovement(lua_State *L) static int lib_pZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_ZMovement(actor)); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 1; } static int lib_pRingZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_RingZMovement(actor); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 0; } static int lib_pSceneryZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SceneryZMovement(actor)); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 1; } static int lib_pPlayerZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_PlayerZMovement(actor); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 0; } @@ -1478,11 +1500,13 @@ static int lib_pSpawnSkidDust(lua_State *L) static int lib_pMovePlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_MovePlayer(player); + P_SetTarget(&tmthing, ptmthing); return 0; } @@ -1671,6 +1695,26 @@ static int lib_pSwitchShield(lua_State *L) return 0; } +static int lib_pPlayerCanEnterSpinGaps(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushboolean(L, P_PlayerCanEnterSpinGaps(player)); + return 1; +} + +static int lib_pPlayerShouldUseSpinHeight(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushboolean(L, P_PlayerShouldUseSpinHeight(player)); + return 1; +} + // P_MAP /////////// @@ -2494,6 +2538,17 @@ static int lib_pGetZAt(lua_State *L) return 1; } +static int lib_pButteredSlope(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + P_ButteredSlope(mobj); + return 0; +} + // R_DEFS //////////// @@ -2808,46 +2863,13 @@ static int lib_sStopSoundByID(lua_State *L) static int lib_sChangeMusic(lua_State *L) { -#ifdef MUSICSLOT_COMPATIBILITY - const char *music_name; - UINT32 music_num, position, prefadems, fadeinms; - char music_compat_name[7]; + UINT32 position, prefadems, fadeinms; - boolean looping; - player_t *player = NULL; - 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; - music_flags = 0; - } - else - { - music_num = 0; - music_name = luaL_checkstring(L, 1); - } - - looping = (boolean)lua_opttrueboolean(L, 2); - -#else const char *music_name = luaL_checkstring(L, 1); boolean looping = (boolean)lua_opttrueboolean(L, 2); player_t *player = NULL; UINT16 music_flags = 0; - //NOHUD -#endif if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) { player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); @@ -2855,13 +2877,7 @@ static int lib_sChangeMusic(lua_State *L) return LUA_ErrInvalid(L, "player_t"); } -#ifdef MUSICSLOT_COMPATIBILITY - if (music_num) - music_flags = (UINT16)((music_num & 0x7FFF0000) >> 16); - else -#endif music_flags = (UINT16)luaL_optinteger(L, 4, 0); - position = (UINT32)luaL_optinteger(L, 5, 0); prefadems = (UINT32)luaL_optinteger(L, 6, 0); fadeinms = (UINT32)luaL_optinteger(L, 7, 0); @@ -3158,33 +3174,7 @@ 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; @@ -3764,6 +3754,9 @@ static luaL_Reg lib[] = { {"M_GetColorAfter",lib_pGetColorAfter}, {"M_GetColorBefore",lib_pGetColorBefore}, + // m_misc + {"M_MapNumber",lib_mMapNumber}, + // m_random {"P_RandomFixed",lib_pRandomFixed}, {"P_RandomByte",lib_pRandomByte}, @@ -3872,6 +3865,8 @@ static luaL_Reg lib[] = { {"P_SpawnSpinMobj",lib_pSpawnSpinMobj}, {"P_Telekinesis",lib_pTelekinesis}, {"P_SwitchShield",lib_pSwitchShield}, + {"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps}, + {"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight}, // p_map {"P_CheckPosition",lib_pCheckPosition}, @@ -3932,6 +3927,7 @@ static luaL_Reg lib[] = { // p_slopes {"P_GetZAt",lib_pGetZAt}, + {"P_ButteredSlope",lib_pButteredSlope}, // r_defs {"R_PointToAngle",lib_rPointToAngle}, diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 1949d56bb..9089d19b6 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2016-2020 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2016-2020 by Sonic Team Junior. +// Copyright (C) 2016-2021 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 5344fee76..414d9692a 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,7 +28,7 @@ return luaL_error(L, "HUD rendering code should not call this function!"); #define NOHOOK if (!lua_lumploading)\ return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); -static const char *cvname = NULL; +static consvar_t *this_cvar; void Got_Luacmd(UINT8 **cp, INT32 playernum) { @@ -273,16 +273,13 @@ static int lib_comBufInsertText(lua_State *L) return 0; } -void LUA_CVarChanged(const char *name) +void LUA_CVarChanged(void *cvar) { - cvname = name; + this_cvar = cvar; } static void Lua_OnChange(void) { - I_Assert(gL != NULL); - I_Assert(cvname != NULL); - /// \todo Network this! XD_LUAVAR lua_pushcfunction(gL, LUA_GetErrorMessage); @@ -291,13 +288,10 @@ static void Lua_OnChange(void) // From CV_OnChange registry field, get the function for this cvar by name. lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange"); I_Assert(lua_istable(gL, -1)); - lua_getfield(gL, -1, cvname); // get function + lua_pushlightuserdata(gL, this_cvar); + lua_rawget(gL, -2); // get function - // From the CV_Vars registry field, get the cvar's userdata by name. - lua_getfield(gL, LUA_REGISTRYINDEX, "CV_Vars"); - I_Assert(lua_istable(gL, -1)); - lua_getfield(gL, -1, cvname); // get consvar_t* userdata. - lua_remove(gL, -2); // pop the CV_Vars table. + LUA_RawPushUserdata(gL, this_cvar); LUA_Call(gL, 1, 0, 1); // call function(cvar) lua_pop(gL, 1); // pop CV_OnChange table @@ -312,15 +306,12 @@ static int lib_cvRegisterVar(lua_State *L) luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. NOHOOK - cvar = lua_newuserdata(L, sizeof(consvar_t)); - luaL_getmetatable(L, META_CVAR); - lua_setmetatable(L, -2); + cvar = ZZ_Calloc(sizeof(consvar_t)); + LUA_PushUserdata(L, cvar, META_CVAR); #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e); #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) - memset(cvar, 0x00, sizeof(consvar_t)); // zero everything by default - lua_pushnil(L); while (lua_next(L, 1)) { // stack: cvar table, cvar userdata, key/index, value @@ -369,7 +360,7 @@ static int lib_cvRegisterVar(lua_State *L) lua_getfield(L, LUA_REGISTRYINDEX, "CV_PossibleValue"); I_Assert(lua_istable(L, 5)); - lua_pushvalue(L, 2); // cvar userdata + lua_pushlightuserdata(L, cvar); cvpv = lua_newuserdata(L, sizeof(CV_PossibleValue_t) * (count+1)); lua_rawset(L, 5); lua_pop(L, 1); // pop CV_PossibleValue registry table @@ -397,8 +388,9 @@ static int lib_cvRegisterVar(lua_State *L) TYPEERROR("func", LUA_TFUNCTION) lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); I_Assert(lua_istable(L, 5)); + lua_pushlightuserdata(L, cvar); lua_pushvalue(L, 4); - lua_setfield(L, 5, cvar->name); + lua_rawset(L, 5); lua_pop(L, 1); cvar->func = Lua_OnChange; } @@ -415,19 +407,6 @@ static int lib_cvRegisterVar(lua_State *L) if ((cvar->flags & CV_CALL) && !cvar->func) return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function\n"), cvar->name); - // stack: cvar table, cvar userdata - lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars"); - I_Assert(lua_istable(L, 3)); - - lua_getfield(L, 3, cvar->name); - if (lua_type(L, -1) != LUA_TNIL) - return luaL_error(L, M_GetText("Variable %s is already defined\n"), cvar->name); - lua_pop(L, 1); - - lua_pushvalue(L, 2); - lua_setfield(L, 3, cvar->name); - lua_pop(L, 1); - // actually time to register it to the console now! Finally! cvar->flags |= CV_MODIFIED; CV_RegisterVar(cvar); @@ -440,7 +419,8 @@ static int lib_cvRegisterVar(lua_State *L) static int lib_cvFindVar(lua_State *L) { - LUA_PushLightUserdata(L, CV_FindVar(luaL_checkstring(L,1)), META_CVAR); + const char *name = luaL_checkstring(L, 1); + LUA_PushUserdata(L, CV_FindVar(name), META_CVAR); return 1; } @@ -450,7 +430,7 @@ static int CVarSetFunction void (*Set)(consvar_t *, const char *), void (*SetValue)(consvar_t *, INT32) ){ - consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); if (cvar->flags & CV_NOLUA) return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name); @@ -482,7 +462,7 @@ static int lib_cvStealthSet(lua_State *L) static int lib_cvAddValue(lua_State *L) { - consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); if (cvar->flags & CV_NOLUA) return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name); @@ -541,7 +521,7 @@ static luaL_Reg lib[] = { static int cvar_get(lua_State *L) { - consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); const char *field = luaL_checkstring(L, 2); if(fastcmp(field,"name")) diff --git a/src/lua_hook.h b/src/lua_hook.h index 5cfcb8360..e3af951f5 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -12,109 +12,122 @@ #include "r_defs.h" #include "d_player.h" +#include "s_sound.h" -enum hook { - hook_NetVars=0, - hook_MapChange, - hook_MapLoad, - hook_PlayerJoin, - hook_PreThinkFrame, - hook_ThinkFrame, - hook_PostThinkFrame, - hook_MobjSpawn, - hook_MobjCollide, - hook_MobjLineCollide, - hook_MobjMoveCollide, - hook_TouchSpecial, - hook_MobjFuse, - hook_MobjThinker, - hook_BossThinker, - hook_ShouldDamage, - hook_MobjDamage, - hook_MobjDeath, - hook_BossDeath, - hook_MobjRemoved, - hook_JumpSpecial, - hook_AbilitySpecial, - hook_SpinSpecial, - hook_JumpSpinSpecial, - hook_BotTiccmd, - hook_BotAI, - hook_BotRespawn, - hook_LinedefExecute, - hook_PlayerMsg, - hook_HurtMsg, - hook_PlayerSpawn, - hook_ShieldSpawn, - hook_ShieldSpecial, - hook_MobjMoveBlocked, - hook_MapThingSpawn, - hook_FollowMobj, - hook_PlayerCanDamage, - hook_PlayerQuit, - hook_IntermissionThinker, - hook_TeamSwitch, - hook_ViewpointSwitch, - hook_SeenPlayer, - hook_PlayerThink, - hook_ShouldJingleContinue, - hook_GameQuit, - hook_PlayerCmd, - hook_MusicChange, +/* +Do you know what an 'X Macro' is? Such a macro is called over each element of +a list and expands the input. I use it for the hook lists because both an enum +and array of hook names need to be kept in order. The X Macro handles this +automatically. +*/ - hook_MAX // last hook -}; -extern const char *const hookNames[]; +#define MOBJ_HOOK_LIST(X) \ + X (MobjSpawn),/* P_SpawnMobj */\ + X (MobjCollide),/* PIT_CheckThing */\ + X (MobjLineCollide),/* ditto */\ + X (MobjMoveCollide),/* tritto */\ + X (TouchSpecial),/* P_TouchSpecialThing */\ + X (MobjFuse),/* when mobj->fuse runs out */\ + X (MobjThinker),/* P_MobjThinker, P_SceneryThinker */\ + X (BossThinker),/* P_GenericBossThinker */\ + X (ShouldDamage),/* P_DamageMobj (Should mobj take damage?) */\ + X (MobjDamage),/* P_DamageMobj (Mobj actually takes damage!) */\ + X (MobjDeath),/* P_KillMobj */\ + X (BossDeath),/* A_BossDeath */\ + X (MobjRemoved),/* P_RemoveMobj */\ + X (BotRespawn),/* B_CheckRespawn */\ + X (MobjMoveBlocked),/* P_XYMovement (when movement is blocked) */\ + X (MapThingSpawn),/* P_SpawnMapThing */\ + X (FollowMobj),/* P_PlayerAfterThink Smiles mobj-following */\ + +#define HOOK_LIST(X) \ + X (NetVars),/* add to archive table (netsave) */\ + X (MapChange),/* (before map load) */\ + X (MapLoad),\ + X (PlayerJoin),/* Got_AddPlayer */\ + X (PreThinkFrame)/* frame (before mobj and player thinkers) */,\ + X (ThinkFrame),/* frame (after mobj and player thinkers) */\ + X (PostThinkFrame),/* frame (at end of tick, ie after overlays, precipitation, specials) */\ + X (JumpSpecial),/* P_DoJumpStuff (Any-jumping) */\ + X (AbilitySpecial),/* P_DoJumpStuff (Double-jumping) */\ + X (SpinSpecial),/* P_DoSpinAbility (Spin button effect) */\ + X (JumpSpinSpecial),/* P_DoJumpStuff (Spin button effect (mid-air)) */\ + X (BotTiccmd),/* B_BuildTiccmd */\ + X (PlayerMsg),/* chat messages */\ + X (HurtMsg),/* imhurttin */\ + X (PlayerSpawn),/* G_SpawnPlayer */\ + X (ShieldSpawn),/* P_SpawnShieldOrb */\ + X (ShieldSpecial),/* shield abilities */\ + X (PlayerCanDamage),/* P_PlayerCanDamage */\ + X (PlayerQuit),\ + X (IntermissionThinker),/* Y_Ticker */\ + X (TeamSwitch),/* team switching in... uh... *what* speak, spit it the fuck out */\ + X (ViewpointSwitch),/* spy mode (no trickstabs) */\ + X (SeenPlayer),/* MT_NAMECHECK */\ + X (PlayerThink),/* P_PlayerThink */\ + X (GameQuit),\ + X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ + X (MusicChange),\ + X (PlayerHeight),/* override player height */\ + X (PlayerCanEnterSpinGaps),\ + X (KeyDown),\ + X (KeyUp),\ + +#define STRING_HOOK_LIST(X) \ + X (BotAI),/* B_BuildTailsTiccmd by skin name */\ + X (LinedefExecute),\ + X (ShouldJingleContinue),/* should jingle of the given music continue playing */\ + +/* +I chose to access the hook enums through a macro as well. This could provide +a hint to lookup the macro's definition instead of the enum's definition. +(Since each enumeration is not defined in the source code, but by the list +macros above, it is not greppable.) The name passed to the macro can also be +grepped and found in the lists above. +*/ + +#define MOBJ_HOOK(name) mobjhook_ ## name +#define HOOK(name) hook_ ## name +#define STRING_HOOK(name) stringhook_ ## name + +enum { MOBJ_HOOK_LIST (MOBJ_HOOK) MOBJ_HOOK(MAX) }; +enum { HOOK_LIST (HOOK) HOOK(MAX) }; +enum { STRING_HOOK_LIST (STRING_HOOK) STRING_HOOK(MAX) }; + +/* dead simple, LUA_HOOK(GameQuit) */ +#define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) extern boolean hook_cmd_running; -void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load) -void LUAh_MapLoad(void); // Hook for map load -void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer -void LUAh_PreThinkFrame(void); // Hook for frame (before mobj and player thinkers) -void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers) -void LUAh_PostThinkFrame(void); // Hook for frame (at end of tick, ie after overlays, precipitation, specials) -boolean LUAh_MobjHook(mobj_t *mo, enum hook which); -boolean LUAh_PlayerHook(player_t *plr, enum hook which); -#define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type -UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which); -UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which); -#define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type -#define LUAh_MobjLineCollide(thing, line) LUAh_MobjLineCollideHook(thing, line, hook_MobjLineCollide) // Hook for PIT_CheckThing by (thing) mobj type -#define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type -boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type -#define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type -boolean LUAh_MobjThinker(mobj_t *mo); // Hook for P_MobjThinker or P_SceneryThinker by mobj type -#define LUAh_BossThinker(mo) LUAh_MobjHook(mo, hook_BossThinker) // Hook for P_GenericBossThinker by mobj type -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Should mobj take damage?) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for P_KillMobj by mobj type -#define LUAh_BossDeath(mo) LUAh_MobjHook(mo, hook_BossDeath) // Hook for A_BossDeath by mobj type -#define LUAh_MobjRemoved(mo) LUAh_MobjHook(mo, hook_MobjRemoved) // Hook for P_RemoveMobj by mobj type -#define LUAh_JumpSpecial(player) LUAh_PlayerHook(player, hook_JumpSpecial) // Hook for P_DoJumpStuff (Any-jumping) -#define LUAh_AbilitySpecial(player) LUAh_PlayerHook(player, hook_AbilitySpecial) // Hook for P_DoJumpStuff (Double-jumping) -#define LUAh_SpinSpecial(player) LUAh_PlayerHook(player, hook_SpinSpecial) // Hook for P_DoSpinAbility (Spin button effect) -#define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air)) -boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd -boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name -boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails); // Hook for B_CheckRespawn -boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for hurt messages -#define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer -#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb -#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities -#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) -boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type -boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following -UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage -void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting -void LUAh_IntermissionThinker(void); // Hook for Y_Ticker -boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... -UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode -boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK -#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink -boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing -void LUAh_GameQuit(boolean quitting); // Hook for game quitting -boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart) -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes +void LUA_HookVoid(int hook); + +int LUA_HookMobj(mobj_t *, int hook); +int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); +void LUA_HookInt(INT32 integer, int hook); +void LUA_HookBool(boolean value, int hook); +int LUA_HookPlayer(player_t *, int hook); +int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); + +void LUA_HookThinkFrame(void); +int LUA_HookMobjLineCollide(mobj_t *, line_t *); +int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher); +int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); +int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); +int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); +int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); +void LUA_HookLinedefExecute(line_t *, mobj_t *, sector_t *); +int LUA_HookPlayerMsg(int source, int target, int flags, char *msg); +int LUA_HookHurtMsg(player_t *, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); +int LUA_HookMapThingSpawn(mobj_t *, mapthing_t *); +int LUA_HookFollowMobj(player_t *, mobj_t *); +int LUA_HookPlayerCanDamage(player_t *, mobj_t *); +void LUA_HookPlayerQuit(player_t *, kickreason_t); +int LUA_HookTeamSwitch(player_t *, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); +int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); +int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend); +int LUA_HookShouldJingleContinue(player_t *, const char *musname); +int LUA_HookPlayerCmd(player_t *, ticcmd_t *); +int LUA_HookMusicChange(const char *oldname, struct MusicChange *); +fixed_t LUA_HookPlayerHeight(player_t *player); +int LUA_HookPlayerCanEnterSpinGaps(player_t *player); +int LUA_HookKey(INT32 keycode, int hooktype); // Hooks for key events diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 29c15a4de..39aa5ea18 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,1947 +27,1075 @@ #include "d_netcmd.h" // for cv_perfstats #include "i_system.h" // I_GetPreciseTime -static UINT8 hooksAvailable[(hook_MAX/8)+1]; +/* ========================================================================= + ABSTRACTION + ========================================================================= */ -const char *const hookNames[hook_MAX+1] = { - "NetVars", - "MapChange", - "MapLoad", - "PlayerJoin", - "PreThinkFrame", - "ThinkFrame", - "PostThinkFrame", - "MobjSpawn", - "MobjCollide", - "MobjLineCollide", - "MobjMoveCollide", - "TouchSpecial", - "MobjFuse", - "MobjThinker", - "BossThinker", - "ShouldDamage", - "MobjDamage", - "MobjDeath", - "BossDeath", - "MobjRemoved", - "JumpSpecial", - "AbilitySpecial", - "SpinSpecial", - "JumpSpinSpecial", - "BotTiccmd", - "BotAI", - "BotRespawn", - "LinedefExecute", - "PlayerMsg", - "HurtMsg", - "PlayerSpawn", - "ShieldSpawn", - "ShieldSpecial", - "MobjMoveBlocked", - "MapThingSpawn", - "FollowMobj", - "PlayerCanDamage", - "PlayerQuit", - "IntermissionThinker", - "TeamSwitch", - "ViewpointSwitch", - "SeenPlayer", - "PlayerThink", - "ShouldJingleContinue", - "GameQuit", - "PlayerCmd", - "MusicChange", - NULL +static const char * const mobjHookNames[] = { MOBJ_HOOK_LIST (TOSTR) NULL }; +static const char * const hookNames[] = { HOOK_LIST (TOSTR) NULL }; + +static const char * const stringHookNames[] = { + STRING_HOOK_LIST (TOSTR) NULL }; -// Hook metadata -struct hook_s +typedef struct { + int numHooks; + int *ids; +} hook_t; + +typedef struct { + int numGeneric; + int ref; +} stringhook_t; + +static hook_t hookIds[HOOK(MAX)]; +static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)]; + +// Lua tables are used to lookup string hook ids. +static stringhook_t stringHooks[STRING_HOOK(MAX)]; + +// This will be indexed by hook id, the value of which fetches the registry. +static int * hookRefs; + +// After a hook errors once, don't print the error again. +static UINT8 * hooksErrored; + +static int errorRef; + +static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) { - struct hook_s *next; - enum hook type; - UINT16 id; - union { - mobjtype_t mt; - char *str; - } s; - boolean error; -}; -typedef struct hook_s* hook_p; + return + ( + mobjHookIds [MT_NULL] [hook_type].numHooks > 0 || + mobjHookIds[mobj_type][hook_type].numHooks > 0 + ); +} -#define FMT_HOOKID "hook_%d" +static int hook_in_list +( + const char * const name, + const char * const * const list +){ + int type; -// For each mobj type, a linked list to its thinker and collision hooks. -// That way, we don't have to iterate through all the hooks. -// We could do that with all other mobj hooks, but it would probably just be -// a waste of memory since they are only called occasionally. Probably... -static hook_p mobjthinkerhooks[NUMMOBJTYPES]; -static hook_p mobjcollidehooks[NUMMOBJTYPES]; + for (type = 0; list[type] != NULL; ++type) + { + if (strcmp(name, list[type]) == 0) + break; + } -// For each mobj type, a linked list for other mobj hooks -static hook_p mobjhooks[NUMMOBJTYPES]; + return type; +} -// A linked list for player hooks -static hook_p playerhooks; - -// A linked list for linedef executor hooks -static hook_p linedefexecutorhooks; - -// For other hooks, a unique linked list -hook_p roothook; - -static void PushHook(lua_State *L, hook_p hookp) +static void get_table(lua_State *L) { - lua_pushfstring(L, FMT_HOOKID, hookp->id); - lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, -1); + lua_rawget(L, -3); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_createtable(L, 1, 0); + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, -5); + } + + lua_remove(L, -2); +} + +static void add_hook_to_table(lua_State *L, int id, int n) +{ + lua_pushnumber(L, id); + lua_rawseti(L, -2, n); +} + +static void add_string_hook(lua_State *L, int type, int id) +{ + stringhook_t * hook = &stringHooks[type]; + + char * string = NULL; + + switch (type) + { + case STRING_HOOK(BotAI): + case STRING_HOOK(ShouldJingleContinue): + if (lua_isstring(L, 3)) + { // lowercase copy + string = Z_StrDup(lua_tostring(L, 3)); + strlwr(string); + } + break; + + case STRING_HOOK(LinedefExecute): + string = Z_StrDup(luaL_checkstring(L, 3)); + strupr(string); + break; + } + + if (hook->ref > 0) + lua_getref(L, hook->ref); + else + { + lua_newtable(L); + lua_pushvalue(L, -1); + hook->ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + if (string) + { + lua_pushstring(L, string); + get_table(L); + add_hook_to_table(L, id, 1 + lua_objlen(L, -1)); + } + else + add_hook_to_table(L, id, ++hook->numGeneric); +} + +static void add_hook(hook_t *map, int id) +{ + Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids, + PU_STATIC, &map->ids); + map->ids[map->numHooks++] = id; +} + +static void add_mobj_hook(lua_State *L, int hook_type, int id) +{ + mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL); + + luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t"); + + add_hook(&mobjHookIds[mobj_type][hook_type], id); } // Takes hook, function, and additional arguments (mobj type to act on, etc.) static int lib_addHook(lua_State *L) { - static struct hook_s hook = {NULL, 0, 0, {0}, false}; - static UINT32 nextid; - hook_p hookp, *lastp; + static int nextid; - hook.type = luaL_checkoption(L, 1, NULL, hookNames); - lua_remove(L, 1); - - luaL_checktype(L, 1, LUA_TFUNCTION); + const char * name; + int type; if (!lua_lumploading) return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); - switch(hook.type) + name = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + + /* this is a very special case */ + if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX)) { - // Take a mobjtype enum which this hook is specifically for. - case hook_MobjSpawn: - case hook_MobjCollide: - case hook_MobjLineCollide: - case hook_MobjMoveCollide: - case hook_TouchSpecial: - case hook_MobjFuse: - case hook_MobjThinker: - case hook_BossThinker: - case hook_ShouldDamage: - case hook_MobjDamage: - case hook_MobjDeath: - case hook_BossDeath: - case hook_MobjRemoved: - case hook_HurtMsg: - case hook_MobjMoveBlocked: - case hook_MapThingSpawn: - case hook_FollowMobj: - hook.s.mt = MT_NULL; - if (lua_isnumber(L, 2)) - hook.s.mt = lua_tonumber(L, 2); - luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t"); - break; - case hook_BotAI: - case hook_ShouldJingleContinue: - hook.s.str = NULL; - if (lua_isstring(L, 2)) - { // lowercase copy - hook.s.str = Z_StrDup(lua_tostring(L, 2)); - strlwr(hook.s.str); - } - break; - case hook_LinedefExecute: // Linedef executor functions - hook.s.str = Z_StrDup(luaL_checkstring(L, 2)); - strupr(hook.s.str); - break; - default: - break; + add_string_hook(L, type, nextid); } - lua_settop(L, 1); // lua stack contains only the function now. - - hooksAvailable[hook.type/8] |= 1<<(hook.type%8); - - // set hook.id to the highest id + 1 - hook.id = nextid++; - - // Special cases for some hook types (see the comments above mobjthinkerhooks declaration) - switch(hook.type) + else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX)) { - case hook_MobjThinker: - lastp = &mobjthinkerhooks[hook.s.mt]; - break; - case hook_MobjCollide: - case hook_MobjLineCollide: - case hook_MobjMoveCollide: - lastp = &mobjcollidehooks[hook.s.mt]; - break; - case hook_MobjSpawn: - case hook_TouchSpecial: - case hook_MobjFuse: - case hook_BossThinker: - case hook_ShouldDamage: - case hook_MobjDamage: - case hook_MobjDeath: - case hook_BossDeath: - case hook_MobjRemoved: - case hook_MobjMoveBlocked: - case hook_MapThingSpawn: - case hook_FollowMobj: - lastp = &mobjhooks[hook.s.mt]; - break; - case hook_JumpSpecial: - case hook_AbilitySpecial: - case hook_SpinSpecial: - case hook_JumpSpinSpecial: - case hook_PlayerSpawn: - case hook_PlayerCanDamage: - case hook_TeamSwitch: - case hook_ViewpointSwitch: - case hook_SeenPlayer: - case hook_ShieldSpawn: - case hook_ShieldSpecial: - case hook_PlayerThink: - lastp = &playerhooks; - break; - case hook_LinedefExecute: - lastp = &linedefexecutorhooks; - break; - default: - lastp = &roothook; - break; + add_mobj_hook(L, type, nextid); + } + else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX)) + { + add_hook(&hookIds[type], nextid); + } + else + { + return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name)); } - // iterate the hook metadata structs - // set lastp to the last hook struct's "next" pointer. - for (hookp = *lastp; hookp; hookp = hookp->next) - lastp = &hookp->next; - // allocate a permanent memory struct to stuff hook. - hookp = ZZ_Alloc(sizeof(struct hook_s)); - memcpy(hookp, &hook, sizeof(struct hook_s)); - // tack it onto the end of the linked list. - *lastp = hookp; + if (!(nextid & 7)) + { + Z_Realloc(hooksErrored, + BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored, + PU_STATIC, &hooksErrored); + hooksErrored[nextid >> 3] = 0; + } + + Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs); // set the hook function in the registry. - lua_pushfstring(L, FMT_HOOKID, hook.id); - lua_pushvalue(L, 1); - lua_settable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 2);/* the function */ + hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; } int LUA_HookLib(lua_State *L) { - memset(hooksAvailable,0,sizeof(UINT8[(hook_MAX/8)+1])); - roothook = NULL; + lua_pushcfunction(L, LUA_GetErrorMessage); + errorRef = luaL_ref(L, LUA_REGISTRYINDEX); + lua_register(L, "addHook", lib_addHook); + return 0; } -boolean LUAh_MobjHook(mobj_t *mo, enum hook which) +typedef struct Hook_State Hook_State; +typedef void (*Hook_Callback)(Hook_State *); + +struct Hook_State { + INT32 status;/* return status to calling function */ + void * userdata; + int hook_type; + mobjtype_t mobj_type;/* >0 if mobj hook */ + const char * string;/* used to fetch table, ran first if set */ + int top;/* index of last argument passed to hook */ + int id;/* id to fetch ref */ + int values;/* num arguments passed to hook */ + int results;/* num values returned by hook */ + Hook_Callback results_handler;/* callback when hook successfully returns */ +}; + +enum { + EINDEX = 1,/* error handler */ + SINDEX = 2,/* string itself is pushed in case of string hook */ +}; + +static void push_error_handler(void) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return false; + lua_getref(gL, errorRef); +} - I_Assert(mo->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type])) - return false; +/* repush hook string */ +static void push_string(void) +{ + lua_pushvalue(gL, SINDEX); +} +static boolean start_hook_stack(void) +{ lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); + push_error_handler(); + return true; +} - // Look for all generic mobj hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) +static boolean init_hook_type +( + Hook_State * hook, + int status, + int hook_type, + mobjtype_t mobj_type, + const char * string, + int nonzero +){ + hook->status = status; + + if (nonzero) { - if (hookp->type != which) - continue; + hook->hook_type = hook_type; + hook->mobj_type = mobj_type; + hook->string = string; + return start_hook_stack(); + } + else + return false; +} - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; +static boolean prepare_hook +( + Hook_State * hook, + int default_status, + int hook_type +){ + return init_hook_type(hook, default_status, + hook_type, 0, NULL, + hookIds[hook_type].numHooks); +} + +static boolean prepare_mobj_hook +( + Hook_State * hook, + int default_status, + int hook_type, + mobjtype_t mobj_type +){ + return init_hook_type(hook, default_status, + hook_type, mobj_type, NULL, + mobj_hook_available(hook_type, mobj_type)); +} + +static boolean prepare_string_hook +( + Hook_State * hook, + int default_status, + int hook_type, + const char * string +){ + if (init_hook_type(hook, default_status, + hook_type, 0, string, + stringHooks[hook_type].ref)) + { + lua_pushstring(gL, string); + return true; + } + else + return false; +} + +static void init_hook_call +( + Hook_State * hook, + int values, + int results, + Hook_Callback results_handler +){ + hook->top = lua_gettop(gL); + hook->values = values; + hook->results = results; + hook->results_handler = results_handler; +} + +static void get_hook(Hook_State *hook, const int *ids, int n) +{ + hook->id = ids[n]; + lua_getref(gL, hookRefs[hook->id]); +} + +static void get_hook_from_table(Hook_State *hook, int n) +{ + lua_rawgeti(gL, -1, n); + hook->id = lua_tonumber(gL, -1); + lua_pop(gL, 1); + lua_getref(gL, hookRefs[hook->id]); +} + +static int call_single_hook_no_copy(Hook_State *hook) +{ + if (lua_pcall(gL, hook->values, hook->results, EINDEX) == 0) + { + if (hook->results > 0) + { + (*hook->results_handler)(hook); + lua_pop(gL, hook->results); + } + } + else + { + /* print the error message once */ + if (cv_debug & DBG_LUA || !in_bit_array(hooksErrored, hook->id)) + { + CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(gL, -1)); + set_bit_array(hooksErrored, hook->id); } - if (lua_toboolean(gL, -1)) - hooked = true; lua_pop(gL, 1); } - for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; + return 1; +} - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } +static int call_single_hook(Hook_State *hook) +{ + int i; + + for (i = -(hook->values) + 1; i <= 0; ++i) + lua_pushvalue(gL, hook->top + i); + + return call_single_hook_no_copy(hook); +} + +static int call_hook_table_for(Hook_State *hook, int n) +{ + int k; + + for (k = 1; k <= n; ++k) + { + get_hook_from_table(hook, k); + call_single_hook(hook); + } + + return n; +} + +static int call_hook_table(Hook_State *hook) +{ + return call_hook_table_for(hook, lua_objlen(gL, -1)); +} + +static int call_mapped(Hook_State *hook, const hook_t *map) +{ + int k; + + for (k = 0; k < map->numHooks; ++k) + { + get_hook(hook, map->ids, k); + call_single_hook(hook); + } + + return map->numHooks; +} + +static int call_string_hooks(Hook_State *hook) +{ + const stringhook_t *map = &stringHooks[hook->hook_type]; + + int calls = 0; + + lua_getref(gL, map->ref); + + /* call generic string hooks first */ + calls += call_hook_table_for(hook, map->numGeneric); + + push_string(); + lua_rawget(gL, -2); + calls += call_hook_table(hook); + + return calls; +} + +static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) +{ + return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); +} + +static int call_hooks +( + Hook_State * hook, + int values, + int results, + Hook_Callback results_handler +){ + int calls = 0; + + init_hook_call(hook, values, results, results_handler); + + if (hook->string) + { + calls += call_string_hooks(hook); + } + else if (hook->mobj_type > 0) + { + /* call generic mobj hooks first */ + calls += call_mobj_type_hooks(hook, MT_NULL); + calls += call_mobj_type_hooks(hook, hook->mobj_type); + + ps_lua_mobjhooks += calls; + } + else + calls += call_mapped(hook, &hookIds[hook->hook_type]); + + lua_settop(gL, 0); + + return calls; +} + +/* ========================================================================= + COMMON RESULT HANDLERS + ========================================================================= */ + +#define res_none NULL + +static void res_true(Hook_State *hook) +{ + if (lua_toboolean(gL, -1)) + hook->status = true; +} + +static void res_false(Hook_State *hook) +{ + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + hook->status = false; +} + +static void res_force(Hook_State *hook) +{ + if (!lua_isnil(gL, -1)) + { if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + hook->status = 1; // Force yes + else + hook->status = 2; // Force no } - - lua_settop(gL, 0); - return hooked; } -boolean LUAh_PlayerHook(player_t *plr, enum hook which) +/* ========================================================================= + GENERALISED HOOKS + ========================================================================= */ + +int LUA_HookMobj(mobj_t *mobj, int hook_type) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, false, hook_type, mobj->type)) { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, plr, META_PLAYER); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, mobj, META_MOBJ); + call_hooks(&hook, 1, 1, res_true); } - - lua_settop(gL, 0); - return hooked; + return hook.status; } -// Hook for map change (before load) -void LUAh_MapChange(INT16 mapnumber) +int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_MapChange/8] & (1<<(hook_MapChange%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - lua_pushinteger(gL, mapnumber); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, hook_type, t1->type)) { - if (hookp->type != hook_MapChange) - continue; - - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + LUA_PushUserdata(gL, t1, META_MOBJ); + LUA_PushUserdata(gL, t2, META_MOBJ); + call_hooks(&hook, 2, 1, res_force); } - - lua_settop(gL, 0); + return hook.status; } -// Hook for map load -void LUAh_MapLoad(void) +void LUA_HookVoid(int type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_MapLoad/8] & (1<<(hook_MapLoad%8)))) - return; + Hook_State hook; + if (prepare_hook(&hook, 0, type)) + call_hooks(&hook, 0, 0, res_none); +} - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - lua_pushinteger(gL, gamemap); - - for (hookp = roothook; hookp; hookp = hookp->next) +void LUA_HookInt(INT32 number, int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, hook_type)) { - if (hookp->type != hook_MapLoad) - continue; - - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + lua_pushinteger(gL, number); + call_hooks(&hook, 1, 0, res_none); } - - lua_settop(gL, 0); } -// Hook for Got_AddPlayer -void LUAh_PlayerJoin(int playernum) +void LUA_HookBool(boolean value, int hook_type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PlayerJoin/8] & (1<<(hook_PlayerJoin%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - lua_pushinteger(gL, playernum); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, 0, hook_type)) { - if (hookp->type != hook_PlayerJoin) - continue; - - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + lua_pushboolean(gL, value); + call_hooks(&hook, 1, 0, res_none); } - - lua_settop(gL, 0); } -// Hook for frame (before mobj and player thinkers) -void LUAh_PreThinkFrame(void) +int LUA_HookPlayer(player_t *player, int hook_type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PreThinkFrame/8] & (1<<(hook_PreThinkFrame%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, false, hook_type)) { - if (hookp->type != hook_PreThinkFrame) - continue; - - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, 1, res_true); } - - lua_pop(gL, 1); // Pop error handler + return hook.status; } -// Hook for frame (after mobj and player thinkers) -void LUAh_ThinkFrame(void) +int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) { - hook_p hookp; + Hook_State hook; + if (prepare_hook(&hook, false, hook_type)) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, cmd, META_TICCMD); + + if (hook_type == HOOK(PlayerCmd)) + hook_cmd_running = true; + + call_hooks(&hook, 2, 1, res_true); + + if (hook_type == HOOK(PlayerCmd)) + hook_cmd_running = false; + } + return hook.status; +} + +/* ========================================================================= + SPECIALIZED HOOKS + ========================================================================= */ + +void LUA_HookThinkFrame(void) +{ + const int type = HOOK(ThinkFrame); + // variables used by perf stats int hook_index = 0; - int time_taken = 0; - if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8)))) - return; + precise_t time_taken = 0; - lua_pushcfunction(gL, LUA_GetErrorMessage); + Hook_State hook; - for (hookp = roothook; hookp; hookp = hookp->next) + const hook_t * map = &hookIds[type]; + int k; + + if (prepare_hook(&hook, 0, type)) { - if (hookp->type != hook_ThinkFrame) - continue; + init_hook_call(&hook, 0, 0, res_none); - if (cv_perfstats.value == 3) - time_taken = I_GetPreciseTime(); - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - if (cv_perfstats.value == 3) + for (k = 0; k < map->numHooks; ++k) { - lua_Debug ar; - time_taken = I_GetPreciseTime() - time_taken; - // we need the function, let's just retrieve it again - PushHook(gL, hookp); - lua_getinfo(gL, ">S", &ar); - PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); - hook_index++; - } - } + get_hook(&hook, map->ids, k); - lua_pop(gL, 1); // Pop error handler -} - -// Hook for frame (at end of tick, ie after overlays, precipitation, specials) -void LUAh_PostThinkFrame(void) -{ - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PostThinkFrame/8] & (1<<(hook_PostThinkFrame%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PostThinkFrame) - continue; - - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - } - - lua_pop(gL, 1); // Pop error handler -} - -// Hook for mobj collisions -UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) -{ - hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return 0; - - I_Assert(thing1->type < NUMMOBJTYPES); - - if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing1->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj collision hooks - for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldCollide; -} - -UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which) -{ - hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return 0; - - I_Assert(thing->type < NUMMOBJTYPES); - - if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj collision hooks - for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing, META_MOBJ); - LUA_PushUserdata(gL, line, META_LINE); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjcollidehooks[thing->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing, META_MOBJ); - LUA_PushUserdata(gL, line, META_LINE); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldCollide; -} - -// Hook for mobj thinkers -boolean LUAh_MobjThinker(mobj_t *mo) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8)))) - return false; - - I_Assert(mo->type < NUMMOBJTYPES); - - if (!(mobjthinkerhooks[MT_NULL] || mobjthinkerhooks[mo->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj thinker hooks - for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next) - { - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next) - { - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_TouchSpecialThing by mobj type -boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8)))) - return false; - - I_Assert(special->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[special->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic touch special hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_TouchSpecial) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[special->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_TouchSpecial) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_DamageMobj by mobj type (Should mobj take damage?) -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8)))) - return 0; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic should damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldDamage) - continue; - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} - -// Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8)))) - return false; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_KillMobj by mobj type -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8)))) - return false; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj death hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDeath) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDeath) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_BuildTiccmd -boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotTiccmd) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, bot, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_BuildTailsTiccmd by skin name -boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotAI - || (hookp->s.str && strcmp(hookp->s.str, ((skin_t*)tails->skin)->name))) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, sonic, META_MOBJ); - LUA_PushUserdata(gL, tails, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 8, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - - // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. - if (lua_istable(gL, 2+1)) { - boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false; -#define CHECKFIELD(field) \ - lua_getfield(gL, 2+1, #field);\ - if (lua_toboolean(gL, -1))\ - field = true;\ - lua_pop(gL, 1); - - CHECKFIELD(forward) - CHECKFIELD(backward) - CHECKFIELD(left) - CHECKFIELD(right) - CHECKFIELD(strafeleft) - CHECKFIELD(straferight) - CHECKFIELD(jump) - CHECKFIELD(spin) -#undef CHECKFIELD - B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin); - } else - B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8)); - - lua_pop(gL, 8); - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_CheckRespawn -boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails) -{ - hook_p hookp; - UINT8 shouldRespawn = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_BotRespawn/8] & (1<<(hook_BotRespawn%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotRespawn) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, sonic, META_MOBJ); - LUA_PushUserdata(gL, tails, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldRespawn = 1; // Force yes - else - shouldRespawn = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldRespawn; -} - -// Hook for linedef executors -boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) - { - if (strcmp(hookp->s.str, line->stringargs[0])) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, line, META_LINE); - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, sector, META_SECTOR); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -} - - -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PlayerMsg) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player - if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c - lua_pushinteger(gL, 3); // type - lua_pushnil(gL); // target - } else if (target == -1) { // sayteam - lua_pushinteger(gL, 1); // type - lua_pushnil(gL); // target - } else if (target == 0) { // say - lua_pushinteger(gL, 0); // type - lua_pushnil(gL); // target - } else { // sayto - lua_pushinteger(gL, 2); // type - LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target + if (cv_perfstats.value == 3) + { + lua_pushvalue(gL, -1);/* need the function again */ + time_taken = I_GetPreciseTime(); } - lua_pushstring(gL, msg); // msg - } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - lua_settop(gL, 0); - return hooked; + call_single_hook(&hook); + + if (cv_perfstats.value == 3) + { + lua_Debug ar; + time_taken = I_GetPreciseTime() - time_taken; + lua_getinfo(gL, ">S", &ar); + PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + hook_index++; + } + } + + lua_settop(gL, 0); + } } - -// Hook for hurt messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) +int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjLineCollide), mobj->type)) { - if (hookp->type != hook_HurtMsg - || (hookp->s.mt && !(inflictor && hookp->s.mt == inflictor->type))) - continue; + LUA_PushUserdata(gL, mobj, META_MOBJ); + LUA_PushUserdata(gL, line, META_LINE); + call_hooks(&hook, 2, 1, res_force); + } + return hook.status; +} - if (lua_gettop(gL) == 1) +int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) +{ + Hook_State hook; + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(TouchSpecial), special->type)) + { + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); + call_hooks(&hook, 2, 1, res_true); + } + return hook.status; +} + +static int damage_hook +( + mobj_t *target, + mobj_t *inflictor, + mobj_t *source, + INT32 damage, + UINT8 damagetype, + int hook_type, + int values, + Hook_Callback results_handler +){ + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, hook_type, target->type)) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + if (values == 5) + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + call_hooks(&hook, values, 1, results_handler); + } + return hook.status; +} + +int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +{ + return damage_hook(target, inflictor, source, damage, damagetype, + MOBJ_HOOK(ShouldDamage), 5, res_force); +} + +int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +{ + return damage_hook(target, inflictor, source, damage, damagetype, + MOBJ_HOOK(MobjDamage), 5, res_true); +} + +int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) +{ + return damage_hook(target, inflictor, source, 0, damagetype, + MOBJ_HOOK(MobjDeath), 4, res_true); +} + +typedef struct { + mobj_t * tails; + ticcmd_t * cmd; +} BotAI_State; + +static boolean checkbotkey(const char *field) +{ + return lua_toboolean(gL, -1) && strcmp(lua_tostring(gL, -2), field) == 0; +} + +static void res_botai(Hook_State *hook) +{ + BotAI_State *botai = hook->userdata; + + int k[8]; + + int fields = 0; + + // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. + if (lua_istable(gL, -8)) { + lua_pushnil(gL); // key + while (lua_next(gL, -9)) { +#define CHECK(n, f) (checkbotkey(f) ? (k[(n)-1] = 1) : 0) + if ( + CHECK(1, "forward") || CHECK(2, "backward") || + CHECK(3, "left") || CHECK(4, "right") || + CHECK(5, "strafeleft") || CHECK(6, "straferight") || + CHECK(7, "jump") || CHECK(8, "spin") + ){ + if (8 <= ++fields) + { + lua_pop(gL, 2); // pop key and value + break; + } + } + + lua_pop(gL, 1); // pop value +#undef CHECK + } + } else { + while (fields < 8) { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); + k[fields] = lua_toboolean(gL, -8 + fields); + fields++; } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); } - lua_settop(gL, 0); - return hooked; + B_KeysToTiccmd(botai->tails, botai->cmd, + k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]); + + hook->status = true; } -void LUAh_NetArchiveHook(lua_CFunction archFunc) +int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) { - hook_p hookp; - int errorhandlerindex; - if (!gL || !(hooksAvailable[hook_NetVars/8] & (1<<(hook_NetVars%8)))) - return; + const char *skin = ((skin_t *)tails->skin)->name; - // stack: tables - I_Assert(lua_gettop(gL) > 0); - I_Assert(lua_istable(gL, -1)); + Hook_State hook; + BotAI_State botai; - lua_pushcfunction(gL, LUA_GetErrorMessage); - errorhandlerindex = lua_gettop(gL); - - // tables becomes an upvalue of archFunc - lua_pushvalue(gL, -2); - lua_pushcclosure(gL, archFunc, 1); - // stack: tables, archFunc - - for (hookp = roothook; hookp; hookp = hookp->next) + if (prepare_string_hook(&hook, false, STRING_HOOK(BotAI), skin)) { - if (hookp->type != hook_NetVars) - continue; + LUA_PushUserdata(gL, sonic, META_MOBJ); + LUA_PushUserdata(gL, tails, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); // archFunc - if (lua_pcall(gL, 1, 0, errorhandlerindex)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + botai.tails = tails; + botai.cmd = cmd; + + hook.userdata = &botai; + + call_hooks(&hook, 2, 8, res_botai); } - lua_pop(gL, 2); // Pop archFunc and error handler - // stack: tables + return hook.status; } -boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing) +void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8)))) - return false; - - if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj map thing spawn hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_string_hook + (&hook, 0, STRING_HOOK(LinedefExecute), line->stringargs[0])) { - if (hookp->type != hook_MapThingSpawn) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, mthing, META_MAPTHING); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, line, META_LINE); + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, sector, META_SECTOR); + ps_lua_mobjhooks += call_hooks(&hook, 3, 0, res_none); } - - for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MapThingSpawn) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, mthing, META_MAPTHING); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; } -// Hook for P_PlayerAfterThink Smiles mobj-following -boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj) +int LUA_HookPlayerMsg(int source, int target, int flags, char *msg) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8)))) - return 0; - - if (!(mobjhooks[MT_NULL] || mobjhooks[mobj->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj follow item hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, false, HOOK(PlayerMsg))) { - if (hookp->type != hook_FollowMobj) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, mobj, META_MOBJ); + LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player + if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c + lua_pushinteger(gL, 3); // type + lua_pushnil(gL); // target + } else if (target == -1) { // sayteam + lua_pushinteger(gL, 1); // type + lua_pushnil(gL); // target + } else if (target == 0) { // say + lua_pushinteger(gL, 0); // type + lua_pushnil(gL); // target + } else { // sayto + lua_pushinteger(gL, 2); // type + LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + lua_pushstring(gL, msg); // msg + call_hooks(&hook, 4, 1, res_true); } - - for (hookp = mobjhooks[mobj->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_FollowMobj) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, mobj, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; + return hook.status; } -// Hook for P_PlayerCanDamage -UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj) +int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { - hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_PlayerCanDamage/8] & (1<<(hook_PlayerCanDamage%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, false, HOOK(HurtMsg))) { - if (hookp->type != hook_PlayerCanDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, mobj, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); + call_hooks(&hook, 4, 1, res_true); } - - lua_settop(gL, 0); - return shouldCollide; + return hook.status; } -void LUAh_PlayerQuit(player_t *plr, kickreason_t reason) +void LUA_HookNetArchive(lua_CFunction archFunc) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + const hook_t * map = &hookIds[HOOK(NetVars)]; + Hook_State hook; + /* this is a remarkable case where the stack isn't reset */ + if (map->numHooks > 0) { - if (hookp->type != hook_PlayerQuit) - continue; + // stack: tables + I_Assert(lua_gettop(gL) > 0); + I_Assert(lua_istable(gL, -1)); - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit - lua_pushinteger(gL, reason); // Reason for quitting - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + push_error_handler(); + lua_insert(gL, EINDEX); + + // tables becomes an upvalue of archFunc + lua_pushvalue(gL, -1); + lua_pushcclosure(gL, archFunc, 1); + // stack: tables, archFunc + + init_hook_call(&hook, 1, 0, res_none); + call_mapped(&hook, map); + + lua_pop(gL, 1); // pop archFunc + lua_remove(gL, EINDEX); // pop error handler + // stack: tables } - - lua_settop(gL, 0); } -// Hook for Y_Ticker -void LUAh_IntermissionThinker(void) +int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(MapThingSpawn), mobj->type)) { - if (hookp->type != hook_IntermissionThinker) - continue; - - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } + LUA_PushUserdata(gL, mobj, META_MOBJ); + LUA_PushUserdata(gL, mthing, META_MAPTHING); + call_hooks(&hook, 2, 1, res_true); } - - lua_pop(gL, 1); // Pop error handler + return hook.status; } -// Hook for team switching -// It's just an edit of LUAh_ViewpointSwitch. -boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) +int LUA_HookFollowMobj(player_t *player, mobj_t *mobj) { - hook_p hookp; - boolean canSwitchTeam = true; - if (!gL || !(hooksAvailable[hook_TeamSwitch/8] & (1<<(hook_TeamSwitch%8)))) - return true; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(FollowMobj), mobj->type)) { - if (hookp->type != hook_TeamSwitch) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - lua_pushinteger(gL, newteam); - lua_pushboolean(gL, fromspectators); - lua_pushboolean(gL, tryingautobalance); - lua_pushboolean(gL, tryingscramble); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) - canSwitchTeam = false; // Can't switch team - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + call_hooks(&hook, 2, 1, res_true); } - - lua_settop(gL, 0); - return canSwitchTeam; + return hook.status; } -// Hook for spy mode -UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) +int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj) { - hook_p hookp; - UINT8 canSwitchView = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ViewpointSwitch/8] & (1<<(hook_ViewpointSwitch%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hud_running = true; // local hook - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, 0, HOOK(PlayerCanDamage))) { - if (hookp->type != hook_ViewpointSwitch) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); - lua_pushboolean(gL, forced); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave canSwitchView = 0. - if (lua_toboolean(gL, -1)) - canSwitchView = 1; // Force viewpoint switch - else - canSwitchView = 2; // Skip viewpoint switch - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + call_hooks(&hook, 2, 1, res_force); } - - lua_settop(gL, 0); - - hud_running = false; - - return canSwitchView; + return hook.status; } -// Hook for MT_NAMECHECK -boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) +void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason) { - hook_p hookp; - boolean hasSeenPlayer = true; - if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8)))) - return true; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hud_running = true; // local hook - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, 0, HOOK(PlayerQuit))) { - if (hookp->type != hook_SeenPlayer) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, seenfriend, META_PLAYER); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) - hasSeenPlayer = false; // Hasn't seen player - lua_pop(gL, 1); + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + call_hooks(&hook, 2, 0, res_none); } - - lua_settop(gL, 0); - - hud_running = false; - - return hasSeenPlayer; } -boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname) +int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) { - hook_p hookp; - boolean keepplaying = false; - if (!gL || !(hooksAvailable[hook_ShouldJingleContinue/8] & (1<<(hook_ShouldJingleContinue%8)))) - return true; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hud_running = true; // local hook - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, true, HOOK(TeamSwitch))) { - if (hookp->type != hook_ShouldJingleContinue - || (hookp->s.str && strcmp(hookp->s.str, musname))) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - lua_pushstring(gL, musname); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1) && lua_toboolean(gL, -1)) - keepplaying = true; // Keep playing this boolean - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushinteger(gL, newteam); + lua_pushboolean(gL, fromspectators); + lua_pushboolean(gL, tryingautobalance); + lua_pushboolean(gL, tryingscramble); + call_hooks(&hook, 5, 1, res_false); } - - lua_settop(gL, 0); - - hud_running = false; - - return keepplaying; + return hook.status; } -// Hook for game quitting -void LUAh_GameQuit(boolean quitting) +int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_GameQuit/8] & (1<<(hook_GameQuit%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, 0, HOOK(ViewpointSwitch))) { - if (hookp->type != hook_GameQuit) - continue; + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); + lua_pushboolean(gL, forced); - PushHook(gL, hookp); - lua_pushboolean(gL, quitting); - if (lua_pcall(gL, 1, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } + hud_running = true; // local hook + call_hooks(&hook, 3, 1, res_force); + hud_running = false; } - - lua_pop(gL, 1); // Pop error handler + return hook.status; +} + +int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend) +{ + Hook_State hook; + if (prepare_hook(&hook, true, HOOK(SeenPlayer))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, seenfriend, META_PLAYER); + + hud_running = true; // local hook + call_hooks(&hook, 2, 1, res_false); + hud_running = false; + } + return hook.status; +} + +int LUA_HookShouldJingleContinue(player_t *player, const char *musname) +{ + Hook_State hook; + if (prepare_string_hook + (&hook, false, STRING_HOOK(ShouldJingleContinue), musname)) + { + LUA_PushUserdata(gL, player, META_PLAYER); + push_string(); + + hud_running = true; // local hook + call_hooks(&hook, 2, 1, res_true); + hud_running = false; + } + return hook.status; } -// Hook for building player's ticcmd struct (Ported from SRB2Kart) boolean hook_cmd_running = false; -boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd) + +static void update_music_name(struct MusicChange *musicchange) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerCmd/8] & (1<<(hook_PlayerCmd%8)))) - return false; + size_t length; + const char * new = lua_tolstring(gL, -6, &length); - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hook_cmd_running = true; - for (hookp = roothook; hookp; hookp = hookp->next) + if (length < 7) { - if (hookp->type != hook_PlayerCmd) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + strcpy(musicchange->newname, new); + lua_pushvalue(gL, -6);/* may as well keep it for next call */ + } + else + { + memcpy(musicchange->newname, new, 6); + musicchange->newname[6] = '\0'; + lua_pushlstring(gL, new, 6); } - lua_settop(gL, 0); - hook_cmd_running = false; - return hooked; + lua_replace(gL, -7); } -// Hook for music changes -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, - UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms) +static void res_musicchange(Hook_State *hook) { - hook_p hookp; - boolean hooked = false; + struct MusicChange *musicchange = hook->userdata; - if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8)))) - return false; + // output 1: true, false, or string musicname override + if (lua_isstring(gL, -6)) + update_music_name(musicchange); + else if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) + hook->status = true; - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); + // output 2: mflags override + if (lua_isnumber(gL, -5)) + *musicchange->mflags = lua_tonumber(gL, -5); + // output 3: looping override + if (lua_isboolean(gL, -4)) + *musicchange->looping = lua_toboolean(gL, -4); + // output 4: position override + if (lua_isnumber(gL, -3)) + *musicchange->position = lua_tonumber(gL, -3); + // output 5: prefadems override + if (lua_isnumber(gL, -2)) + *musicchange->prefadems = lua_tonumber(gL, -2); + // output 6: fadeinms override + if (lua_isnumber(gL, -1)) + *musicchange->fadeinms = lua_tonumber(gL, -1); +} - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MusicChange) +int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) +{ + const int type = HOOK(MusicChange); + const hook_t * map = &hookIds[type]; + + Hook_State hook; + + int k; + + if (prepare_hook(&hook, false, type)) + { + init_hook_call(&hook, 7, 6, res_musicchange); + hook.userdata = param; + + lua_pushstring(gL, oldname);/* the only constant value */ + lua_pushstring(gL, param->newname);/* semi constant */ + + for (k = 0; k <= map->numHooks; ++k) { - PushHook(gL, hookp); - lua_pushstring(gL, oldname); - lua_pushstring(gL, newname); - lua_pushinteger(gL, *mflags); - lua_pushboolean(gL, *looping); - lua_pushinteger(gL, *position); - lua_pushinteger(gL, *prefadems); - lua_pushinteger(gL, *fadeinms); - if (lua_pcall(gL, 7, 6, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); - lua_pop(gL, 1); - continue; - } + get_hook(&hook, map->ids, k); - // 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_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + lua_pushinteger(gL, *param->mflags); + lua_pushboolean(gL, *param->looping); + lua_pushinteger(gL, *param->position); + lua_pushinteger(gL, *param->prefadems); + lua_pushinteger(gL, *param->fadeinms); - lua_pop(gL, 7); // Pop returned values and error handler + call_single_hook_no_copy(&hook); } - lua_settop(gL, 0); - newname[6] = 0; - return hooked; + lua_settop(gL, 0); + } + + return hook.status; +} + +static void res_playerheight(Hook_State *hook) +{ + if (!lua_isnil(gL, -1)) + { + fixed_t returnedheight = lua_tonumber(gL, -1); + // 0 height has... strange results, but it's not problematic like negative heights are. + // when an object's height is set to a negative number directly with lua, it's forced to 0 instead. + // here, I think it's better to ignore negatives so that they don't replace any results of previous hooks! + if (returnedheight >= 0) + hook->status = returnedheight; + } +} + +fixed_t LUA_HookPlayerHeight(player_t *player) +{ + Hook_State hook; + if (prepare_hook(&hook, -1, HOOK(PlayerHeight))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, 1, res_playerheight); + } + return hook.status; +} + +int LUA_HookPlayerCanEnterSpinGaps(player_t *player) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, HOOK(PlayerCanEnterSpinGaps))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, 1, res_force); + } + return hook.status; +} + +int LUA_HookKey(INT32 keycode, int hooktype) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, hooktype)) + { + lua_pushinteger(gL, keycode); + call_hooks(&hook, 1, 0, res_true); + } + return hook.status; } diff --git a/src/lua_hud.h b/src/lua_hud.h index 1e9dca00b..d2f5bceca 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -37,7 +37,9 @@ enum hud { hud_tabemblems, // Intermission hud_intermissiontally, + hud_intermissiontitletext, hud_intermissionmessages, + hud_intermissionemeralds, hud_MAX }; @@ -49,4 +51,4 @@ void LUAh_GameHUD(player_t *stplyr); void LUAh_ScoresHUD(void); void LUAh_TitleHUD(void); void LUAh_TitleCardHUD(player_t *stplayr); -void LUAh_IntermissionHUD(void); +void LUAh_IntermissionHUD(boolean failedstage); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 8d451e99c..9a3e676d5 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -63,7 +63,9 @@ static const char *const hud_disable_options[] = { "tabemblems", "intermissiontally", + "intermissiontitletext", "intermissionmessages", + "intermissionemeralds", NULL}; enum hudinfo { @@ -857,6 +859,26 @@ static int libd_drawScaledNameTag(lua_State *L) return 0; } +static int libd_drawLevelTitle(lua_State *L) +{ + INT32 x; + INT32 y; + const char *str; + INT32 flags; + + HUDONLY + + x = luaL_checkinteger(L, 1); + y = luaL_checkinteger(L, 2); + str = luaL_checkstring(L, 3); + flags = luaL_optinteger(L, 4, 0); + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + + V_DrawLevelTitle(x, y, flags, str); + return 0; +} + static int libd_stringWidth(lua_State *L) { const char *str = luaL_checkstring(L, 1); @@ -886,6 +908,20 @@ static int libd_nameTagWidth(lua_State *L) return 1; } +static int libd_levelTitleWidth(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, V_LevelNameWidth(luaL_checkstring(L, 1))); + return 1; +} + +static int libd_levelTitleHeight(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, V_LevelNameHeight(luaL_checkstring(L, 1))); + return 1; +} + static int libd_getColormap(lua_State *L) { INT32 skinnum = TC_DEFAULT; @@ -1091,10 +1127,13 @@ static luaL_Reg lib_draw[] = { {"drawString", libd_drawString}, {"drawNameTag", libd_drawNameTag}, {"drawScaledNameTag", libd_drawScaledNameTag}, + {"drawLevelTitle", libd_drawLevelTitle}, {"fadeScreen", libd_fadeScreen}, // misc {"stringWidth", libd_stringWidth}, {"nameTagWidth", libd_nameTagWidth}, + {"levelTitleWidth", libd_levelTitleWidth}, + {"levelTitleHeight", libd_levelTitleHeight}, // m_random {"RandomFixed",libd_RandomFixed}, {"RandomByte",libd_RandomByte}, @@ -1384,7 +1423,7 @@ void LUAh_TitleCardHUD(player_t *stplayr) hud_running = false; } -void LUAh_IntermissionHUD(void) +void LUAh_IntermissionHUD(boolean failedstage) { if (!gL || !(hudAvailable & (1<= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, PLAYER1INPUTDOWN(i)); + return 1; +} + +static int lib_gameControl2Down(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, PLAYER2INPUTDOWN(i)); + return 1; +} + +static int lib_gameControlToKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, gamecontrol[i][0]); + lua_pushinteger(L, gamecontrol[i][1]); + return 2; +} + +static int lib_gameControl2ToKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, gamecontrolbis[i][0]); + lua_pushinteger(L, gamecontrolbis[i][1]); + return 2; +} + +static int lib_joyAxis(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushinteger(L, JoyAxis(i)); + return 1; +} + +static int lib_joy2Axis(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushinteger(L, Joy2Axis(i)); + return 1; +} + +static int lib_keyNumToString(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushstring(L, G_KeyNumToString(i)); + return 1; +} + +static int lib_keyStringToNum(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); + lua_pushinteger(L, G_KeyStringToNum(str)); + return 1; +} + +static int lib_keyNumPrintable(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushboolean(L, i >= 32 && i <= 127); + return 1; +} + +static int lib_shiftKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i >= 32 && i <= 127) + lua_pushinteger(L, shiftxform[i]); + return 1; +} + +static int lib_getMouseGrab(lua_State *L) +{ + lua_pushboolean(L, I_GetMouseGrab()); + return 1; +} + +static int lib_setMouseGrab(lua_State *L) +{ + boolean grab = luaL_checkboolean(L, 1); + I_SetMouseGrab(grab); + return 0; +} + +static int lib_getCursorPosition(lua_State *L) +{ + int x, y; + I_GetCursorPosition(&x, &y); + lua_pushinteger(L, x); + lua_pushinteger(L, y); + return 2; +} + +static luaL_Reg lib[] = { + {"G_GameControlDown", lib_gameControlDown}, + {"G_GameControl2Down", lib_gameControl2Down}, + {"G_GameControlToKeyNum", lib_gameControlToKeyNum}, + {"G_GameControl2ToKeyNum", lib_gameControl2ToKeyNum}, + {"G_JoyAxis", lib_joyAxis}, + {"G_Joy2Axis", lib_joy2Axis}, + {"G_KeyNumToString", lib_keyNumToString}, + {"G_KeyStringToNum", lib_keyStringToNum}, + {"HU_KeyNumPrintable", lib_keyNumPrintable}, + {"HU_ShiftKeyNum", lib_shiftKeyNum}, + {"I_GetMouseGrab", lib_getMouseGrab}, + {"I_SetMouseGrab", lib_setMouseGrab}, + {"I_GetCursorPosition", lib_getCursorPosition}, + {NULL, NULL} +}; + +/////////////////// +// gamekeydown[] // +/////////////////// + +static int lib_getGameKeyDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMINPUTS) + return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); + lua_pushboolean(L, gamekeydown[i]); + return 1; +} + +static int lib_setGameKeyDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 2); + boolean j = luaL_checkboolean(L, 3); + if (i < 0 || i >= NUMINPUTS) + return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); + gamekeydown[i] = j; + return 0; +} + +static int lib_lenGameKeyDown(lua_State *L) +{ + lua_pushinteger(L, NUMINPUTS); + return 1; +} + +/////////// +// MOUSE // +/////////// + +static int mouse_get(lua_State *L) +{ + mouse_t *m = *((mouse_t **)luaL_checkudata(L, 1, META_MOUSE)); + const char *field = luaL_checkstring(L, 2); + + I_Assert(m != NULL); + + if (fastcmp(field,"dx")) + lua_pushinteger(L, m->dx); + else if (fastcmp(field,"dy")) + lua_pushinteger(L, m->dy); + else if (fastcmp(field,"mlookdy")) + lua_pushinteger(L, m->mlookdy); + else if (fastcmp(field,"rdx")) + lua_pushinteger(L, m->rdx); + else if (fastcmp(field,"rdy")) + lua_pushinteger(L, m->rdy); + else if (fastcmp(field,"buttons")) + lua_pushinteger(L, m->buttons); + else + return luaL_error(L, "mouse_t has no field named %s", field); + + return 1; +} + +// #mouse -> 1 or 2 +static int mouse_num(lua_State *L) +{ + mouse_t *m = *((mouse_t **)luaL_checkudata(L, 1, META_MOUSE)); + + I_Assert(m != NULL); + + lua_pushinteger(L, m == &mouse ? 1 : 2); + return 1; +} + +int LUA_InputLib(lua_State *L) +{ + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getGameKeyDown); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setGameKeyDown); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_lenGameKeyDown); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "gamekeydown"); + + luaL_newmetatable(L, META_MOUSE); + lua_pushcfunction(L, mouse_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, mouse_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + // Set global functions + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_register(L, NULL, lib); + return 0; +} diff --git a/src/lua_libs.h b/src/lua_libs.h index fbe8d4878..668eb99b0 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -88,6 +88,8 @@ extern lua_State *gL; #define META_LUABANKS "LUABANKS[]*" +#define META_MOUSE "MOUSE_T*" + boolean luaL_checkboolean(lua_State *L, int narg); int LUA_EnumLib(lua_State *L); @@ -106,3 +108,4 @@ int LUA_TagLib(lua_State *L); int LUA_PolyObjLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); +int LUA_InputLib(lua_State *L); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 016141796..9031c99f1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index b6046ab53..e6f8c98c1 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,6 +16,7 @@ #include "p_local.h" #include "doomstat.h" // for ALL7EMERALDS #include "r_main.h" // for R_PointToDist2 +#include "m_easing.h" #include "lua_script.h" #include "lua_libs.h" @@ -87,6 +88,12 @@ static int lib_finetangent(lua_State *L) return 1; } +static int lib_fixedacos(lua_State *L) +{ + lua_pushangle(L, FixedAcos(luaL_checkfixed(L, 1))); + return 1; +} + // Fixed math //////////////// @@ -185,13 +192,14 @@ static int lib_coloropposite(lua_State *L) return 2; } -static luaL_Reg lib[] = { +static luaL_Reg lib_math[] = { {"abs", lib_abs}, {"min", lib_min}, {"max", lib_max}, {"sin", lib_finesine}, {"cos", lib_finecosine}, {"tan", lib_finetangent}, + {"acos", lib_fixedacos}, {"FixedAngle", lib_fixedangle}, {"fixangle" , lib_fixedangle}, {"AngleFixed", lib_anglefixed}, @@ -223,9 +231,123 @@ static luaL_Reg lib[] = { {NULL, NULL} }; +// +// Easing functions +// + +#define EASINGFUNC(easetype) \ +{ \ + fixed_t start = 0; \ + fixed_t end = FRACUNIT; \ + fixed_t t = luaL_checkfixed(L, 1); \ + int n = lua_gettop(L); \ + if (n == 2) \ + end = luaL_checkfixed(L, 2); \ + else if (n >= 3) \ + { \ + start = luaL_checkfixed(L, 2); \ + end = luaL_checkfixed(L, 3); \ + } \ + lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \ + return 1; \ +} \ + +static int lib_easelinear(lua_State *L) { EASINGFUNC(Linear) } + +static int lib_easeinsine(lua_State *L) { EASINGFUNC(InSine) } +static int lib_easeoutsine(lua_State *L) { EASINGFUNC(OutSine) } +static int lib_easeinoutsine(lua_State *L) { EASINGFUNC(InOutSine) } + +static int lib_easeinquad(lua_State *L) { EASINGFUNC(InQuad) } +static int lib_easeoutquad(lua_State *L) { EASINGFUNC(OutQuad) } +static int lib_easeinoutquad(lua_State *L) { EASINGFUNC(InOutQuad) } + +static int lib_easeincubic(lua_State *L) { EASINGFUNC(InCubic) } +static int lib_easeoutcubic(lua_State *L) { EASINGFUNC(OutCubic) } +static int lib_easeinoutcubic(lua_State *L) { EASINGFUNC(InOutCubic) } + +static int lib_easeinquart(lua_State *L) { EASINGFUNC(InQuart) } +static int lib_easeoutquart(lua_State *L) { EASINGFUNC(OutQuart) } +static int lib_easeinoutquart(lua_State *L) { EASINGFUNC(InOutQuart) } + +static int lib_easeinquint(lua_State *L) { EASINGFUNC(InQuint) } +static int lib_easeoutquint(lua_State *L) { EASINGFUNC(OutQuint) } +static int lib_easeinoutquint(lua_State *L) { EASINGFUNC(InOutQuint) } + +static int lib_easeinexpo(lua_State *L) { EASINGFUNC(InExpo) } +static int lib_easeoutexpo(lua_State *L) { EASINGFUNC(OutExpo) } +static int lib_easeinoutexpo(lua_State *L) { EASINGFUNC(InOutExpo) } + +#undef EASINGFUNC + +#define EASINGFUNC(easetype) \ +{ \ + boolean useparam = false; \ + fixed_t param = 0; \ + fixed_t start = 0; \ + fixed_t end = FRACUNIT; \ + fixed_t t = luaL_checkfixed(L, 1); \ + int n = lua_gettop(L); \ + if (n == 2) \ + end = luaL_checkfixed(L, 2); \ + else if (n >= 3) \ + { \ + start = (fixed_t)luaL_optinteger(L, 2, start); \ + end = (fixed_t)luaL_optinteger(L, 3, end); \ + if ((n >= 4) && (useparam = (!lua_isnil(L, 4)))) \ + param = luaL_checkfixed(L, 4); \ + } \ + if (useparam) \ + lua_pushfixed(L, (Easing_ ## easetype ## Parameterized)(t, start, end, param)); \ + else \ + lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \ + return 1; \ +} \ + +static int lib_easeinback(lua_State *L) { EASINGFUNC(InBack) } +static int lib_easeoutback(lua_State *L) { EASINGFUNC(OutBack) } +static int lib_easeinoutback(lua_State *L) { EASINGFUNC(InOutBack) } + +#undef EASINGFUNC + +static luaL_Reg lib_ease[] = { + {"linear", lib_easelinear}, + + {"insine", lib_easeinsine}, + {"outsine", lib_easeoutsine}, + {"inoutsine", lib_easeinoutsine}, + + {"inquad", lib_easeinquad}, + {"outquad", lib_easeoutquad}, + {"inoutquad", lib_easeinoutquad}, + + {"incubic", lib_easeincubic}, + {"outcubic", lib_easeoutcubic}, + {"inoutcubic", lib_easeinoutcubic}, + + {"inquart", lib_easeinquart}, + {"outquart", lib_easeoutquart}, + {"inoutquart", lib_easeinoutquart}, + + {"inquint", lib_easeinquint}, + {"outquint", lib_easeoutquint}, + {"inoutquint", lib_easeinoutquint}, + + {"inexpo", lib_easeinexpo}, + {"outexpo", lib_easeoutexpo}, + {"inoutexpo", lib_easeinoutexpo}, + + {"inback", lib_easeinback}, + {"outback", lib_easeoutback}, + {"inoutback", lib_easeinoutback}, + + {NULL, NULL} +}; + int LUA_MathLib(lua_State *L) { lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_register(L, NULL, lib); + luaL_register(L, NULL, lib_math); + luaL_register(L, "ease", lib_ease); return 0; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 65adceb15..cf8ccab2c 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -12,6 +12,7 @@ #include "doomdef.h" #include "fastcmp.h" +#include "r_data.h" #include "r_skins.h" #include "p_local.h" #include "g_game.h" @@ -654,8 +655,13 @@ static int mobj_set(lua_State *L) break; } case mobj_blendmode: - mo->blendmode = (INT32)luaL_checkinteger(L, 3); + { + INT32 blendmode = (INT32)luaL_checkinteger(L, 3); + if (blendmode < 0 || blendmode > AST_OVERLAY) + return luaL_error(L, "mobj.blendmode %d out of range (0 - %d).", blendmode, AST_OVERLAY); + mo->blendmode = blendmode; break; + } case mobj_bnext: return NOSETPOS; case mobj_bprev: diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0eb54808f..06104ff2d 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -795,6 +795,7 @@ static int power_len(lua_State *L) } #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) +#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", field) static int ticcmd_get(lua_State *L) { @@ -813,6 +814,8 @@ static int ticcmd_get(lua_State *L) lua_pushinteger(L, cmd->aiming); else if (fastcmp(field,"buttons")) lua_pushinteger(L, cmd->buttons); + else if (fastcmp(field,"latency")) + lua_pushinteger(L, cmd->latency); else return NOFIELD; @@ -839,6 +842,8 @@ static int ticcmd_set(lua_State *L) cmd->aiming = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"buttons")) cmd->buttons = (UINT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"latency")) + return NOSET; else return NOFIELD; @@ -846,6 +851,7 @@ static int ticcmd_set(lua_State *L) } #undef NOFIELD +#undef NOSET int LUA_PlayerLib(lua_State *L) { diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 2a5bcfbf1..5d76a912d 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_script.c b/src/lua_script.c index 7fd5a98e6..6faff8729 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,6 +20,7 @@ #include "r_state.h" #include "r_sky.h" #include "g_game.h" +#include "g_input.h" #include "f_finale.h" #include "byteptr.h" #include "p_saveg.h" @@ -57,6 +58,7 @@ static lua_CFunction liblist[] = { LUA_PolyObjLib, // polyobj_t LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff + LUA_InputLib, // inputs NULL }; @@ -184,6 +186,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"modeattacking")) { lua_pushboolean(L, modeattacking); return 1; + } else if (fastcmp(word,"metalrecording")) { + lua_pushboolean(L, metalrecording); + return 1; } else if (fastcmp(word,"splitscreen")) { lua_pushboolean(L, splitscreen); return 1; @@ -380,6 +385,14 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word, "gamestate")) { lua_pushinteger(L, gamestate); return 1; + } else if (fastcmp(word, "stagefailed")) { + lua_pushboolean(L, stagefailed); + } else if (fastcmp(word, "mouse")) { + LUA_PushUserdata(L, &mouse, META_MOUSE); + return 1; + } else if (fastcmp(word, "mouse2")) { + LUA_PushUserdata(L, &mouse2, META_MOUSE); + return 1; } return 0; } @@ -429,6 +442,8 @@ int LUA_CheckGlobals(lua_State *L, const char *word) } else if (fastcmp(word, "mapmusflags")) mapmusflags = (UINT16)luaL_checkinteger(L, 2); + else if (fastcmp(word, "stagefailed")) + stagefailed = luaL_checkboolean(L, 2); else return 0; @@ -714,27 +729,6 @@ fixed_t LUA_EvalMath(const char *word) return res; } -/* -LUA_PushUserdata but no userdata is created. -You can't invalidate it therefore. -*/ - -void LUA_PushLightUserdata (lua_State *L, void *data, const char *meta) -{ - if (data) - { - lua_pushlightuserdata(L, data); - luaL_getmetatable(L, meta); - /* - The metatable is the last value on the stack, so this - applies it to the second value, which is the userdata. - */ - lua_setmetatable(L, -2); - } - else - lua_pushnil(L); -} - // Takes a pointer, any pointer, and a metatable name // Creates a userdata for that pointer with the given metatable // Pushes it to the stack and stores it in the registry. @@ -934,6 +928,7 @@ enum ARCH_SLOPE, ARCH_MAPHEADER, ARCH_SKINCOLOR, + ARCH_MOUSE, ARCH_TEND=0xFF, }; @@ -961,6 +956,7 @@ static const struct { {META_SLOPE, ARCH_SLOPE}, {META_MAPHEADER, ARCH_MAPHEADER}, {META_SKINCOLOR, ARCH_SKINCOLOR}, + {META_MOUSE, ARCH_MOUSE}, {NULL, ARCH_NULL} }; @@ -1268,7 +1264,6 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } - case ARCH_SKINCOLOR: { skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex)); @@ -1276,6 +1271,13 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) WRITEUINT16(save_p, info - skincolors); break; } + case ARCH_MOUSE: + { + mouse_t *m = *((mouse_t **)lua_touserdata(gL, myindex)); + WRITEUINT8(save_p, ARCH_MOUSE); + WRITEUINT8(save_p, m == &mouse ? 1 : 2); + break; + } default: WRITEUINT8(save_p, ARCH_NULL); return 2; @@ -1527,6 +1529,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX) case ARCH_SKINCOLOR: LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR); break; + case ARCH_MOUSE: + LUA_PushUserdata(gL, READUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE); + break; case ARCH_TEND: return 1; } @@ -1653,7 +1658,7 @@ void LUA_Archive(void) WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. - LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode + LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode ArchiveTables(); if (gL) @@ -1688,7 +1693,7 @@ void LUA_UnArchive(void) } } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. - LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode + LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode UnArchiveTables(); if (gL) diff --git a/src/lua_script.h b/src/lua_script.h index 77fbb7c1d..e88256941 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -56,10 +56,10 @@ void LUA_UnArchive(void); int LUA_PushGlobals(lua_State *L, const char *word); int LUA_CheckGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c -void LUA_CVarChanged(const char *name); // lua_consolelib.c +void LUA_CVarChanged(void *cvar); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, const char *def, const char *const lst[]); -void LUAh_NetArchiveHook(lua_CFunction archFunc); +void LUA_HookNetArchive(lua_CFunction archFunc); void LUA_PushTaggableObjectArray ( lua_State *L, @@ -87,7 +87,6 @@ typedef enum { LPUSHED_EXISTING, } lpushed_t; -void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta); void LUA_PushUserdata(lua_State *L, void *data, const char *meta); lpushed_t LUA_RawPushUserdata(lua_State *L, void *data); diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 56be6bf4f..e66a379e9 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -53,7 +53,6 @@ enum skin { skin_contspeed, skin_contangle, skin_soundsid, - skin_availability, skin_sprites }; static const char *const skin_opt[] = { @@ -91,7 +90,6 @@ static const char *const skin_opt[] = { "contspeed", "contangle", "soundsid", - "availability", "sprites", NULL}; @@ -209,11 +207,8 @@ static int skin_get(lua_State *L) case skin_soundsid: LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID); break; - case skin_availability: - lua_pushinteger(L, skin->availability); - break; case skin_sprites: - LUA_PushLightUserdata(L, skin->sprites, META_SKINSPRITES); + LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES); break; } return 1; @@ -336,13 +331,13 @@ static const char *const sprites_opt[] = { // skin.sprites[i] -> sprites[i] static int lib_getSkinSprite(lua_State *L) { - spritedef_t *sprites = (spritedef_t *)luaL_checkudata(L, 1, META_SKINSPRITES); + spritedef_t *sprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES); playersprite_t i = luaL_checkinteger(L, 2); if (i < 0 || i >= NUMPLAYERSPRITES*2) return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1); - LUA_PushLightUserdata(L, &sprites[i], META_SKINSPRITESLIST); + LUA_PushUserdata(L, &sprites[i], META_SKINSPRITESLIST); return 1; } @@ -355,7 +350,7 @@ static int lib_numSkinsSprites(lua_State *L) static int sprite_get(lua_State *L) { - spritedef_t *sprite = (spritedef_t *)luaL_checkudata(L, 1, META_SKINSPRITESLIST); + spritedef_t *sprite = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITESLIST); enum spritesopt field = luaL_checkoption(L, 2, NULL, sprites_opt); switch (field) diff --git a/src/lua_taglib.c b/src/lua_taglib.c index c9f320fe8..d0cf385a9 100644 --- a/src/lua_taglib.c +++ b/src/lua_taglib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2020-2021 by James R. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index 82baa6469..65bf8c313 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_aatree.c b/src/m_aatree.c index c0bb739f8..b228ed63d 100644 --- a/src/m_aatree.c +++ b/src/m_aatree.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_aatree.h b/src/m_aatree.h index b784eb17a..5a240394f 100644 --- a/src/m_aatree.h +++ b/src/m_aatree.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.c b/src/m_anigif.c index 41f99254e..fe04a5cb4 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. // Copyright (C) 2013 by "Ninji". -// Copyright (C) 2013-2020 by Sonic Team Junior. +// Copyright (C) 2013-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.h b/src/m_anigif.h index abe05dd96..ca7563b1e 100644 --- a/src/m_anigif.h +++ b/src/m_anigif.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2013-2020 by Sonic Team Junior. +// Copyright (C) 2013-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_argv.c b/src/m_argv.c index 7d43d96bc..453d6e45c 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_argv.h b/src/m_argv.h index 92770f4e9..f39db513f 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_bbox.c b/src/m_bbox.c index 02d534164..e0505fd95 100644 --- a/src/m_bbox.c +++ b/src/m_bbox.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_bbox.h b/src/m_bbox.h index 9b63c61b6..c56bd22c0 100644 --- a/src/m_bbox.h +++ b/src/m_bbox.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cheat.c b/src/m_cheat.c index 6e0fb8c5c..c958bb4a4 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cheat.h b/src/m_cheat.h index ac2540408..ee4ba5f55 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cond.c b/src/m_cond.c index 36fcd7cf2..85d732a48 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -496,6 +496,64 @@ UINT8 M_GotHighEnoughRings(INT32 trings) return false; } +// Gets the skin number for a SECRET_SKIN unlockable. +INT32 M_UnlockableSkinNum(unlockable_t *unlock) +{ + if (unlock->type != SECRET_SKIN) + { + // This isn't a skin unlockable... + return -1; + } + + if (unlock->stringVar && strcmp(unlock->stringVar, "")) + { + // Get the skin from the string. + INT32 skinnum = R_SkinAvailable(unlock->stringVar); + if (skinnum != -1) + { + return skinnum; + } + } + + if (unlock->variable >= 0 && unlock->variable < numskins) + { + // Use the number directly. + return unlock->variable; + } + + // Invalid skin unlockable. + return -1; +} + +// Gets the skin number for a ET_SKIN emblem. +INT32 M_EmblemSkinNum(emblem_t *emblem) +{ + if (emblem->type != ET_SKIN) + { + // This isn't a skin emblem... + return -1; + } + + if (emblem->stringVar && strcmp(emblem->stringVar, "")) + { + // Get the skin from the string. + INT32 skinnum = R_SkinAvailable(emblem->stringVar); + if (skinnum != -1) + { + return skinnum; + } + } + + if (emblem->var >= 0 && emblem->var < numskins) + { + // Use the number directly. + return emblem->var; + } + + // Invalid skin emblem. + return -1; +} + // ---------------- // Misc Emblem shit // ---------------- diff --git a/src/m_cond.h b/src/m_cond.h index 9bb162ff3..b2c6d65e6 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -92,6 +92,7 @@ typedef struct UINT8 sprite; ///< emblem sprite to use, 0 - 25 UINT16 color; ///< skincolor to use INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin) + char *stringVar; ///< String version char hint[110]; ///< Hint for emblem hints menu UINT8 collected; ///< Do you have this emblem? } emblem_t; @@ -116,6 +117,7 @@ typedef struct UINT8 showconditionset; INT16 type; INT16 variable; + char *stringVar; UINT8 nocecho; UINT8 nochecklist; UINT8 unlocked; @@ -132,6 +134,7 @@ typedef struct #define SECRET_WARP 2 // Selectable warp #define SECRET_SOUNDTEST 3 // Sound Test #define SECRET_CREDITS 4 // Enables Credits +#define SECRET_SKIN 5 // Unlocks a skin // If you have more secrets than these variables allow in your game, // you seriously need to get a life. @@ -185,4 +188,7 @@ UINT8 M_GotHighEnoughScore(INT32 tscore); UINT8 M_GotLowEnoughTime(INT32 tictime); UINT8 M_GotHighEnoughRings(INT32 trings); +INT32 M_UnlockableSkinNum(unlockable_t *unlock); +INT32 M_EmblemSkinNum(emblem_t *emblem); + #define M_Achieved(a) ((a) >= MAXCONDITIONSETS || conditionSets[a].achieved) diff --git a/src/m_dllist.h b/src/m_dllist.h index 680c2cd80..65303b4a3 100644 --- a/src/m_dllist.h +++ b/src/m_dllist.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2005 by James Haley -// Copyright (C) 2005-2020 by Sonic Team Junior. +// Copyright (C) 2005-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_easing.c b/src/m_easing.c new file mode 100644 index 000000000..c871d3106 --- /dev/null +++ b/src/m_easing.c @@ -0,0 +1,430 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_easing.c +/// \brief Easing functions +/// Referenced from https://easings.net/ + +#include "m_easing.h" +#include "tables.h" +#include "doomdef.h" + +/* + For the computation of the logarithm, we choose, by trial and error, from among + a sequence of particular factors those, that when multiplied with the function + argument, normalize it to unity. For every factor chosen, we add up the + corresponding logarithm value stored in a table. The sum then corresponds to + the logarithm of the function argument. + + For the integer portion, we would want to choose + 2^i, i = 1, 2, 4, 8, ... + and for the factional part we choose + 1+2^-i, i = 1, 2, 3, 4, 5 ... + + The algorithm for the exponential is closely related and quite literally the inverse + of the logarithm algorithm. From among the sequence of tabulated logarithms for our + chosen factors, we pick those that when subtracted from the function argument ultimately + reduce it to zero. Starting with unity, we multiply with all the factors whose logarithms + we have subtracted in the process. The resulting product corresponds to the result of the exponentiation. + + Logarithms of values greater than unity can be computed by applying the algorithm to the reciprocal + of the function argument (with the negation of the result as appropriate), likewise exponentiation with + negative function arguments requires us negate the function argument and compute the reciprocal at the end. +*/ + +static fixed_t logtabdec[FRACBITS] = +{ + 0x95c1, 0x526a, 0x2b80, 0x1663, + 0xb5d, 0x5b9, 0x2e0, 0x170, + 0xb8, 0x5c, 0x2e, 0x17, + 0x0b, 0x06, 0x03, 0x01 +}; + +static fixed_t fixlog2(fixed_t a) +{ + UINT32 x = a, y = 0; + INT32 t, i, shift = 8; + + if (x > FRACUNIT) + x = FixedDiv(FRACUNIT, x); + + // Integer part + // 1<<19 = 0x80000 + // 1<<18 = 0x40000 + // 1<<17 = 0x20000 + // 1<<16 = 0x10000 + +#define dologtab(i) \ + t = (x << shift); \ + if (t < FRACUNIT) \ + { \ + x = t; \ + y += (1 << (19 - i)); \ + } \ + shift /= 2; + + dologtab(0) + dologtab(1) + dologtab(2) + dologtab(3) + +#undef dologtab + + // Decimal part + for (i = 0; i < FRACBITS; i++) + { + t = x + (x >> (i + 1)); + if (t < FRACUNIT) + { + x = t; + y += logtabdec[i]; + } + } + + if (a <= FRACUNIT) + return -y; + + return y; +} + +// Notice how this is symmetric to fixlog2. +static INT32 fixexp(fixed_t a) +{ + UINT32 x, y; + fixed_t t, i, shift = 8; + + // Underflow prevention. + if (a <= -15 * FRACUNIT) + return 0; + + x = (a < 0) ? (-a) : (a); + y = FRACUNIT; + + // Integer part (see fixlog2) +#define dologtab(i) \ + t = x - (1 << (19 - i)); \ + if (t >= 0) \ + { \ + x = t; \ + y <<= shift; \ + } \ + shift /= 2; + + dologtab(0) + dologtab(1) + dologtab(2) + dologtab(3) + +#undef dologtab + + // Decimal part + for (i = 0; i < FRACBITS; i++) + { + t = (x - logtabdec[i]); + if (t >= 0) + { + x = t; + y += (y >> (i + 1)); + } + } + + if (a < 0) + return FixedDiv(FRACUNIT, y); + + return y; +} + +#define fixpow(x, y) fixexp(FixedMul((y), fixlog2(x))) +#define fixintmul(x, y) FixedMul((x) * FRACUNIT, y) +#define fixintdiv(x, y) FixedDiv(x, (y) * FRACUNIT) +#define fixinterp(start, end, t) FixedMul((FRACUNIT - (t)), start) + FixedMul(t, end) + +// ================== +// EASING FUNCTIONS +// ================== + +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end) + +// +// Linear +// + +EASINGFUNC(Linear) +{ + return fixinterp(start, end, t); +} + +// +// Sine +// + +// This is equivalent to calculating (x * pi) and converting the result from radians into degrees. +#define fixang(x) FixedMul((x), 180*FRACUNIT) + +EASINGFUNC(InSine) +{ + fixed_t c = fixang(t / 2); + fixed_t x = FRACUNIT - FINECOSINE(FixedAngle(c)>>ANGLETOFINESHIFT); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutSine) +{ + fixed_t c = fixang(t / 2); + fixed_t x = FINESINE(FixedAngle(c)>>ANGLETOFINESHIFT); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutSine) +{ + fixed_t c = fixang(t); + fixed_t x = -(FINECOSINE(FixedAngle(c)>>ANGLETOFINESHIFT) - FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +#undef fixang + +// +// Quad +// + +EASINGFUNC(InQuad) +{ + return fixinterp(start, end, FixedMul(t, t)); +} + +EASINGFUNC(OutQuad) +{ + return fixinterp(start, end, FRACUNIT - FixedMul(FRACUNIT - t, FRACUNIT - t)); +} + +EASINGFUNC(InOutQuad) +{ + fixed_t x = t < (FRACUNIT/2) + ? fixintmul(2, FixedMul(t, t)) + : FRACUNIT - fixpow(FixedMul(-2*FRACUNIT, t) + 2*FRACUNIT, 2*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// Cubic +// + +EASINGFUNC(InCubic) +{ + fixed_t x = FixedMul(t, FixedMul(t, t)); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutCubic) +{ + return fixinterp(start, end, FRACUNIT - fixpow(FRACUNIT - t, 3*FRACUNIT)); +} + +EASINGFUNC(InOutCubic) +{ + fixed_t x = t < (FRACUNIT/2) + ? fixintmul(4, FixedMul(t, FixedMul(t, t))) + : FRACUNIT - fixpow(fixintmul(-2, t) + 2*FRACUNIT, 3*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// "Quart" +// + +EASINGFUNC(InQuart) +{ + fixed_t x = FixedMul(FixedMul(t, t), FixedMul(t, t)); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutQuart) +{ + fixed_t x = FRACUNIT - fixpow(FRACUNIT - t, 4 * FRACUNIT); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutQuart) +{ + fixed_t x = t < (FRACUNIT/2) + ? fixintmul(8, FixedMul(FixedMul(t, t), FixedMul(t, t))) + : FRACUNIT - fixpow(fixintmul(-2, t) + 2*FRACUNIT, 4*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// "Quint" +// + +EASINGFUNC(InQuint) +{ + fixed_t x = FixedMul(t, FixedMul(FixedMul(t, t), FixedMul(t, t))); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutQuint) +{ + fixed_t x = FRACUNIT - fixpow(FRACUNIT - t, 5 * FRACUNIT); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutQuint) +{ + fixed_t x = t < (FRACUNIT/2) + ? FixedMul(16*FRACUNIT, FixedMul(t, FixedMul(FixedMul(t, t), FixedMul(t, t)))) + : FRACUNIT - fixpow(fixintmul(-2, t) + 2*FRACUNIT, 5*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// Exponential +// + +EASINGFUNC(InExpo) +{ + fixed_t x = (!t) ? 0 : fixpow(2*FRACUNIT, fixintmul(10, t) - 10*FRACUNIT); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutExpo) +{ + fixed_t x = (t >= FRACUNIT) ? FRACUNIT + : FRACUNIT - fixpow(2*FRACUNIT, fixintmul(-10, t)); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutExpo) +{ + fixed_t x; + + if (!t) + x = 0; + else if (t >= FRACUNIT) + x = FRACUNIT; + else + { + if (t < FRACUNIT / 2) + { + x = fixpow(2*FRACUNIT, fixintmul(20, t) - 10*FRACUNIT); + x = fixintdiv(x, 2); + } + else + { + x = fixpow(2*FRACUNIT, fixintmul(-20, t) + 10*FRACUNIT); + x = fixintdiv((2*FRACUNIT) - x, 2); + } + } + + return fixinterp(start, end, x); +} + +// +// "Back" +// + +#define EASEBACKCONST1 111514 // 1.70158 +#define EASEBACKCONST2 99942 // 1.525 + +static fixed_t EaseInBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c1) +{ + const fixed_t c3 = c1 + FRACUNIT; + fixed_t x = FixedMul(FixedMul(t, t), FixedMul(c3, t) - c1); + return fixinterp(start, end, x); +} + +EASINGFUNC(InBack) +{ + return EaseInBack(t, start, end, EASEBACKCONST1); +} + +static fixed_t EaseOutBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c1) +{ + const fixed_t c3 = c1 + FRACUNIT; + fixed_t x; + t -= FRACUNIT; + x = FRACUNIT + FixedMul(FixedMul(t, t), FixedMul(c3, t) + c1); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutBack) +{ + return EaseOutBack(t, start, end, EASEBACKCONST1); +} + +static fixed_t EaseInOutBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c2) +{ + fixed_t x, y; + const fixed_t f2 = 2*FRACUNIT; + + if (t < FRACUNIT / 2) + { + x = fixpow(FixedMul(t, f2), f2); + y = FixedMul(c2 + FRACUNIT, FixedMul(t, f2)); + x = FixedMul(x, y - c2); + } + else + { + x = fixpow(-(FixedMul(t, f2) - f2), f2); + y = FixedMul(c2 + FRACUNIT, FixedMul(t, f2) - f2); + x = FixedMul(x, y + c2); + x += f2; + } + + x /= 2; + + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutBack) +{ + return EaseInOutBack(t, start, end, EASEBACKCONST2); +} + +#undef EASINGFUNC +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end, fixed_t param) + +EASINGFUNC(InBackParameterized) +{ + return EaseInBack(t, start, end, param); +} + +EASINGFUNC(OutBackParameterized) +{ + return EaseOutBack(t, start, end, param); +} + +EASINGFUNC(InOutBackParameterized) +{ + return EaseInOutBack(t, start, end, param); +} + +#undef EASINGFUNC + +// Function list + +#define EASINGFUNC(type) Easing_ ## type +#define COMMA , + +easingfunc_t easing_funclist[EASE_MAX] = +{ + EASINGFUNCLIST(COMMA) +}; + +// Function names + +#undef EASINGFUNC +#define EASINGFUNC(type) #type + +const char *easing_funcnames[EASE_MAX] = +{ + EASINGFUNCLIST(COMMA) +}; + +#undef COMMA +#undef EASINGFUNC diff --git a/src/m_easing.h b/src/m_easing.h new file mode 100644 index 000000000..435ad35e7 --- /dev/null +++ b/src/m_easing.h @@ -0,0 +1,101 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_easing.h +/// \brief Easing functions + +#ifndef __M_EASING_H__ +#define __M_EASING_H__ + +#include "doomtype.h" +#include "m_fixed.h" + +typedef enum +{ + EASE_LINEAR = 0, + + EASE_INSINE, + EASE_OUTSINE, + EASE_INOUTSINE, + + EASE_INQUAD, + EASE_OUTQUAD, + EASE_INOUTQUAD, + + EASE_INCUBIC, + EASE_OUTCUBIC, + EASE_INOUTCUBIC, + + EASE_INQUART, + EASE_OUTQUART, + EASE_INOUTQUART, + + EASE_INQUINT, + EASE_OUTQUINT, + EASE_INOUTQUINT, + + EASE_INEXPO, + EASE_OUTEXPO, + EASE_INOUTEXPO, + + EASE_INBACK, + EASE_OUTBACK, + EASE_INOUTBACK, + + EASE_MAX, +} easing_t; + +typedef fixed_t (*easingfunc_t)(fixed_t, fixed_t, fixed_t); + +extern easingfunc_t easing_funclist[EASE_MAX]; +extern const char *easing_funcnames[EASE_MAX]; + +#define EASINGFUNCLIST(sep) \ + EASINGFUNC(Linear) sep /* Easing_Linear */ \ + \ + EASINGFUNC(InSine) sep /* Easing_InSine */ \ + EASINGFUNC(OutSine) sep /* Easing_OutSine */ \ + EASINGFUNC(InOutSine) sep /* Easing_InOutSine */ \ + \ + EASINGFUNC(InQuad) sep /* Easing_InQuad */ \ + EASINGFUNC(OutQuad) sep /* Easing_OutQuad */ \ + EASINGFUNC(InOutQuad) sep /* Easing_InOutQuad */ \ + \ + EASINGFUNC(InCubic) sep /* Easing_InCubic */ \ + EASINGFUNC(OutCubic) sep /* Easing_OutCubic */ \ + EASINGFUNC(InOutCubic) sep /* Easing_InOutCubic */ \ + \ + EASINGFUNC(InQuart) sep /* Easing_InQuart */ \ + EASINGFUNC(OutQuart) sep /* Easing_OutQuart */ \ + EASINGFUNC(InOutQuart) sep /* Easing_InOutQuart */ \ + \ + EASINGFUNC(InQuint) sep /* Easing_InQuint */ \ + EASINGFUNC(OutQuint) sep /* Easing_OutQuint */ \ + EASINGFUNC(InOutQuint) sep /* Easing_InOutQuint */ \ + \ + EASINGFUNC(InExpo) sep /* Easing_InExpo */ \ + EASINGFUNC(OutExpo) sep /* Easing_OutExpo */ \ + EASINGFUNC(InOutExpo) sep /* Easing_InOutExpo */ \ + \ + EASINGFUNC(InBack) sep /* Easing_InBack */ \ + EASINGFUNC(OutBack) sep /* Easing_OutBack */ \ + EASINGFUNC(InOutBack) sep /* Easing_InOutBack */ + +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end); + +EASINGFUNCLIST() + +#undef EASINGFUNC +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end, fixed_t param); + +EASINGFUNC(InBackParameterized) /* Easing_InBackParameterized */ +EASINGFUNC(OutBackParameterized) /* Easing_OutBackParameterized */ +EASINGFUNC(InOutBackParameterized) /* Easing_InOutBackParameterized */ + +#undef EASINGFUNC +#endif diff --git a/src/m_fixed.c b/src/m_fixed.c index eb10fd5f8..d40ccd98e 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.h b/src/m_fixed.h index 289ca442a..1cf2f00d1 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -71,7 +71,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f) value [eax] \ modify exact [eax edx] #elif defined (__GNUC__) && defined (__i386__) && !defined (NOASM) - // DJGPP, i386 linux, cygwin or mingw + // i386 linux, cygwin or mingw FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // asm { fixed_t ret; diff --git a/src/m_menu.c b/src/m_menu.c index 516bd34c1..db2aa09c6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -62,6 +62,8 @@ #include "i_joy.h" // for joystick menu controls +#include "p_saveg.h" // Only for NEWSKINSAVES + // Condition Sets #include "m_cond.h" @@ -1322,7 +1324,7 @@ static menuitem_t OP_Camera2ExtendedOptionsMenu[] = enum { op_video_resolution = 1, -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) op_video_fullscreen, #endif op_video_vsync, @@ -1334,7 +1336,7 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_HEADER, NULL, "Screen", NULL, 0}, {IT_STRING | IT_CALL, NULL, "Set Resolution...", M_VideoModeMenu, 6}, -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 11}, #endif {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16}, @@ -1453,7 +1455,7 @@ static menuitem_t OP_OpenGLOptionsMenu[] = #ifdef ALAM_LIGHTING {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 144}, #endif -#if defined (_WINDOWS) && (!((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL))) +#if defined (_WINDOWS) && (!(defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL))) {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 154}, #endif }; @@ -3305,7 +3307,7 @@ boolean M_Responder(event_t *ev) } else if (ev->type == ev_mouse && mousewait < I_GetTime()) { - pmousey += ev->data3; + pmousey -= ev->data3; if (pmousey < lasty-30) { ch = KEY_DOWNARROW; @@ -5166,34 +5168,75 @@ static boolean M_GametypeHasLevels(INT32 gt) static INT32 M_CountRowsToShowOnPlatter(INT32 gt) { - INT32 mapnum = 0, prevmapnum = 0, col = 0, rows = 0; + INT32 col = 0, rows = 0; + INT32 mapIterate = 0; + INT32 headingIterate = 0; + boolean mapAddedAlready[NUMMAPS]; - while (mapnum < NUMMAPS) + memset(mapAddedAlready, 0, sizeof mapAddedAlready); + + for (mapIterate = 0; mapIterate < NUMMAPS; mapIterate++) { - if (M_CanShowLevelOnPlatter(mapnum, gt)) + boolean forceNewRow = true; + + if (mapAddedAlready[mapIterate] == true) { - if (rows == 0) + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(mapIterate, gt) == false) + { + // Don't show this one + continue; + } + + for (headingIterate = mapIterate; headingIterate < NUMMAPS; headingIterate++) + { + boolean wide = false; + + if (mapAddedAlready[headingIterate] == true) + { + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(headingIterate, gt) == false) + { + // Don't show this one + continue; + } + + if (!fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[headingIterate]->selectheading)) + { + // Headers don't match + continue; + } + + wide = (mapheaderinfo[headingIterate]->menuflags & LF2_WIDEICON); + + // preparing next position to drop mapnum into + if (col == 2 // no more space on the row? + || wide || forceNewRow) + { + col = 0; rows++; + } else { - if (col == 2 - || (mapheaderinfo[prevmapnum]->menuflags & LF2_WIDEICON) - || (mapheaderinfo[mapnum]->menuflags & LF2_WIDEICON) - || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading))) - { - col = 0; - rows++; - } - else - col++; + col++; } - prevmapnum = mapnum; + + // Done adding this one + mapAddedAlready[headingIterate] = true; + forceNewRow = wide; } - mapnum++; } if (levellistmode == LLM_CREATESERVER) + { rows++; + } return rows; } @@ -5223,7 +5266,10 @@ static void M_CacheLevelPlatter(void) static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); - INT32 mapnum = 0, prevmapnum = 0, col = 0, row = 0, startrow = 0; + INT32 col = 0, row = 0, startrow = 0; + INT32 mapIterate = 0; // First level of map loop -- find starting points for select headings + INT32 headingIterate = 0; // Second level of map loop -- finding maps that match mapIterate's heading. + boolean mapAddedAlready[NUMMAPS]; if (!numrows) return false; @@ -5240,6 +5286,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) // done here so lsrow and lscol can be set if cv_nextmap is on the platter lsrow = lscol = lshli = lsoffs[0] = lsoffs[1] = 0; + memset(mapAddedAlready, 0, sizeof mapAddedAlready); + if (levellistmode == LLM_CREATESERVER) { sprintf(levelselect.rows[0].header, "Gametype"); @@ -5251,31 +5299,75 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) char_notes = NULL; } - while (mapnum < NUMMAPS) + for (mapIterate = 0; mapIterate < NUMMAPS; mapIterate++) { - if (M_CanShowLevelOnPlatter(mapnum, gt)) + INT32 headerRow = -1; + boolean anyAvailable = false; + boolean forceNewRow = true; + + if (mapAddedAlready[mapIterate] == true) { - const UINT8 actnum = mapheaderinfo[mapnum]->actnum; - const boolean headingisname = (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl)); - const boolean wide = (mapheaderinfo[mapnum]->menuflags & LF2_WIDEICON); + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(mapIterate, gt) == false) + { + // Don't show this one + continue; + } + + for (headingIterate = mapIterate; headingIterate < NUMMAPS; headingIterate++) + { + UINT8 actnum = 0; + boolean headingisname = false; + boolean wide = false; + + if (mapAddedAlready[headingIterate] == true) + { + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(headingIterate, gt) == false) + { + // Don't show this one + continue; + } + + if (!fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[headingIterate]->selectheading)) + { + // Headers don't match + continue; + } + + actnum = mapheaderinfo[headingIterate]->actnum; + headingisname = (fastcmp(mapheaderinfo[headingIterate]->selectheading, mapheaderinfo[headingIterate]->lvlttl)); + wide = (mapheaderinfo[headingIterate]->menuflags & LF2_WIDEICON); // preparing next position to drop mapnum into if (levelselect.rows[startrow].maplist[0]) { if (col == 2 // no more space on the row? - || wide - || (mapheaderinfo[prevmapnum]->menuflags & LF2_WIDEICON) - || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading))) // a new heading is starting? + || wide || forceNewRow) { col = 0; row++; } else + { col++; + } } - levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter - levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); + if (headerRow == -1) + { + // Set where the header row is meant to be + headerRow = row; + } + + levelselect.rows[row].maplist[col] = headingIterate+1; // putting the map on the platter + levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(headingIterate); if ((lswide(row) = wide)) // intentionally assignment { @@ -5283,7 +5375,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) levelselect.rows[row].mapavailable[2] = levelselect.rows[row].mapavailable[1] = levelselect.rows[row].mapavailable[0]; } - if (nextmappick && cv_nextmap.value == mapnum+1) // A little quality of life improvement. + if (nextmappick && cv_nextmap.value == headingIterate+1) // A little quality of life improvement. { lsrow = row; lscol = col; @@ -5292,6 +5384,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) // individual map name if (levelselect.rows[row].mapavailable[col]) { + anyAvailable = true; + if (headingisname) { if (actnum) @@ -5302,7 +5396,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) else if (wide) { // Yes, with LF2_WIDEICON it'll continue on over into the next 17+1 char block. That's alright; col is always zero, the string is contiguous, and the maximum length is lvlttl[22] + ' ' + ZONE + ' ' + INT32, which is about 39 or so - barely crossing into the third column. - char* mapname = G_BuildMapTitle(mapnum+1); + char* mapname = G_BuildMapTitle(headingIterate+1); strcpy(levelselect.rows[row].mapnames[col], (const char *)mapname); Z_Free(mapname); } @@ -5311,9 +5405,9 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) char mapname[22+1+11]; // lvlttl[22] + ' ' + INT32 if (actnum) - sprintf(mapname, "%s %d", mapheaderinfo[mapnum]->lvlttl, actnum); + sprintf(mapname, "%s %d", mapheaderinfo[headingIterate]->lvlttl, actnum); else - strcpy(mapname, mapheaderinfo[mapnum]->lvlttl); + strcpy(mapname, mapheaderinfo[headingIterate]->lvlttl); if (strlen(mapname) >= 17) strcpy(mapname+17-3, "..."); @@ -5322,27 +5416,36 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) } } else - sprintf(levelselect.rows[row].mapnames[col], "???"); - - // creating header text - if (!col && ((row == startrow) || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row-1].maplist[0]-1]->selectheading)))) { - if (!levelselect.rows[row].mapavailable[col]) - sprintf(levelselect.rows[row].header, "???"); - else - { - sprintf(levelselect.rows[row].header, "%s", mapheaderinfo[mapnum]->selectheading); - if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && headingisname) - { - sprintf(levelselect.rows[row].header + strlen(levelselect.rows[row].header), " ZONE"); - } - } + sprintf(levelselect.rows[row].mapnames[col], "???"); } - prevmapnum = mapnum; + // Done adding this one + mapAddedAlready[headingIterate] = true; + forceNewRow = wide; } - mapnum++; + if (headerRow == -1) + { + // Shouldn't happen + continue; + } + + // creating header text + if (anyAvailable == false) + { + sprintf(levelselect.rows[headerRow].header, "???"); + } + else + { + sprintf(levelselect.rows[headerRow].header, "%s", mapheaderinfo[mapIterate]->selectheading); + + if (!(mapheaderinfo[mapIterate]->levelflags & LF_NOZONE) + && fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[mapIterate]->lvlttl)) + { + sprintf(levelselect.rows[headerRow].header + strlen(levelselect.rows[headerRow].header), " ZONE"); + } + } } #ifdef SYMMETRICAL_PLATTER @@ -6234,8 +6337,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/ADDONS\x80 to get & make addons!" +//#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/ADDONS\x80 to get & make addons!" static void M_LoadAddonsPatches(void) { @@ -6937,7 +7040,7 @@ static void M_SelectableClearMenus(INT32 choice) static void M_UltimateCheat(INT32 choice) { (void)choice; - LUAh_GameQuit(true); + LUA_HookBool(true, HOOK(GameQuit)); I_Quit(); } @@ -8580,7 +8683,7 @@ static void M_LoadSelect(INT32 choice) #define VERSIONSIZE 16 #define BADSAVE { savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; } -#define CHECKPOS if (save_p >= end_p) BADSAVE +#define CHECKPOS if (sav_p >= end_p) BADSAVE // Reads the save file to list lives, level, player, etc. // Tails 05-29-2003 static void M_ReadSavegameInfo(UINT32 slot) @@ -8589,10 +8692,13 @@ static void M_ReadSavegameInfo(UINT32 slot) char savename[255]; UINT8 *savebuffer; UINT8 *end_p; // buffer end point, don't read past here - UINT8 *save_p; + UINT8 *sav_p; INT32 fake; // Dummy variable char temp[sizeof(timeattackfolder)]; char vcheck[VERSIONSIZE]; +#ifdef NEWSKINSAVES + INT16 backwardsCompat = 0; +#endif sprintf(savename, savegamename, slot); @@ -8608,19 +8714,19 @@ static void M_ReadSavegameInfo(UINT32 slot) end_p = savebuffer + length; // skip the description field - save_p = savebuffer; + sav_p = savebuffer; // Version check memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, "version %d", VERSION); - if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE - save_p += VERSIONSIZE; + if (strcmp((const char *)sav_p, (const char *)vcheck)) BADSAVE + sav_p += VERSIONSIZE; // dearchive all the modifications // P_UnArchiveMisc() CHECKPOS - fake = READINT16(save_p); + fake = READINT16(sav_p); if (((fake-1) & 8191) >= NUMMAPS) BADSAVE @@ -8637,54 +8743,84 @@ static void M_ReadSavegameInfo(UINT32 slot) savegameinfo[slot].gamemap = fake; CHECKPOS - savegameinfo[slot].numemeralds = READUINT16(save_p)-357; // emeralds + savegameinfo[slot].numemeralds = READUINT16(sav_p)-357; // emeralds CHECKPOS - READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to + READSTRINGN(sav_p, temp, sizeof(temp)); // mod it belongs to if (strcmp(temp, timeattackfolder)) BADSAVE // P_UnArchivePlayer() +#ifdef NEWSKINSAVES CHECKPOS - fake = READUINT16(save_p); - savegameinfo[slot].skinnum = fake & ((1<<5) - 1); - if (savegameinfo[slot].skinnum >= numskins - || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) - BADSAVE - savegameinfo[slot].botskin = fake >> 5; - if (savegameinfo[slot].botskin-1 >= numskins - || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) - BADSAVE + backwardsCompat = READUINT16(sav_p); + + if (backwardsCompat != NEWSKINSAVES) + { + // Backwards compat + savegameinfo[slot].skinnum = backwardsCompat & ((1<<5) - 1); + + if (savegameinfo[slot].skinnum >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) + BADSAVE + + savegameinfo[slot].botskin = backwardsCompat >> 5; + if (savegameinfo[slot].botskin-1 >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) + BADSAVE + } + else +#endif + { + char ourSkinName[SKINNAMESIZE+1]; + char botSkinName[SKINNAMESIZE+1]; + + CHECKPOS + READSTRINGN(sav_p, ourSkinName, SKINNAMESIZE); + savegameinfo[slot].skinnum = R_SkinAvailable(ourSkinName); + + if (savegameinfo[slot].skinnum >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) + BADSAVE + + CHECKPOS + READSTRINGN(sav_p, botSkinName, SKINNAMESIZE); + savegameinfo[slot].botskin = (R_SkinAvailable(botSkinName) + 1); + + if (savegameinfo[slot].botskin-1 >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) + BADSAVE + } CHECKPOS - savegameinfo[slot].numgameovers = READUINT8(save_p); // numgameovers + savegameinfo[slot].numgameovers = READUINT8(sav_p); // numgameovers CHECKPOS - savegameinfo[slot].lives = READSINT8(save_p); // lives + savegameinfo[slot].lives = READSINT8(sav_p); // lives CHECKPOS - savegameinfo[slot].continuescore = READINT32(save_p); // score + savegameinfo[slot].continuescore = READINT32(sav_p); // score CHECKPOS - fake = READINT32(save_p); // continues + fake = READINT32(sav_p); // continues if (useContinues) savegameinfo[slot].continuescore = fake; // File end marker check CHECKPOS - switch (READUINT8(save_p)) + switch (READUINT8(sav_p)) { case 0xb7: { UINT8 i, banksinuse; CHECKPOS - banksinuse = READUINT8(save_p); + banksinuse = READUINT8(sav_p); CHECKPOS if (banksinuse > NUM_LUABANKS) BADSAVE for (i = 0; i < banksinuse; i++) { - (void)READINT32(save_p); + (void)READINT32(sav_p); CHECKPOS } - if (READUINT8(save_p) != 0x1d) + if (READUINT8(sav_p) != 0x1d) BADSAVE } case 0x1d: @@ -8963,7 +9099,7 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) static UINT8 M_SetupChoosePlayerDirect(INT32 choice) { - INT32 skinnum; + INT32 skinnum, botskinnum; UINT8 i; UINT8 firstvalid = 255, lastvalid = 255; boolean allowed = false; @@ -8995,6 +9131,13 @@ static UINT8 M_SetupChoosePlayerDirect(INT32 choice) skinnum = description[i].skinnum[0]; if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) { + botskinnum = description[i].skinnum[1]; + if ((botskinnum != -1) && (!R_SkinUsable(-1, botskinnum))) + { + // Bot skin isn't unlocked + continue; + } + // Handling order. if (firstvalid == 255) firstvalid = i; @@ -11419,9 +11562,9 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join - OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Master server - OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Minimum delay between joins - OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Attempts to resynchronise + OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Master server + OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Minimum delay between joins + OP_ServerOptionsMenu[38].status = IT_GRAYEDOUT; // Attempts to resynchronise } else { @@ -11429,11 +11572,11 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR; - OP_ServerOptionsMenu[35].status = (netgame + OP_ServerOptionsMenu[36].status = (netgame ? IT_GRAYEDOUT : (IT_STRING | IT_CVAR | IT_CV_STRING)); - OP_ServerOptionsMenu[36].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR; + OP_ServerOptionsMenu[38].status = IT_STRING | IT_CVAR; } #endif @@ -12683,13 +12826,13 @@ static void M_DrawControl(void) else { if (keys[0] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[0])); + strcat (tmp, G_KeyNumToString (keys[0])); if (keys[0] != KEY_NULL && keys[1] != KEY_NULL) strcat(tmp," or "); if (keys[1] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[1])); + strcat (tmp, G_KeyNumToString (keys[1])); } @@ -12923,7 +13066,7 @@ static void M_VideoModeMenu(INT32 choice) memset(modedescs, 0, sizeof(modedescs)); -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // FIXME: hack #endif vidm_nummodes = 0; @@ -13366,7 +13509,7 @@ void M_QuitResponse(INT32 ch) if (ch != 'y' && ch != KEY_ENTER) return; - LUAh_GameQuit(true); + LUA_HookBool(true, HOOK(GameQuit)); if (!(netgame || cv_debug)) { S_ResetCaptions(); diff --git a/src/m_menu.h b/src/m_menu.h index 0465128ef..ba9c326a0 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_misc.c b/src/m_misc.c index 74c30dedd..4100a8f17 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -64,8 +64,6 @@ typedef off_t off64_t; #define PRIdS "u" #elif defined (_WIN32) #define PRIdS "Iu" -#elif defined (DJGPP) -#define PRIdS "u" #else #define PRIdS "zu" #endif @@ -165,7 +163,9 @@ consvar_t cv_zlib_window_bitsa = CVAR_INIT ("apng_window_size", "32k", CV_SAVE, consvar_t cv_apng_delay = CVAR_INIT ("apng_speed", "1x", CV_SAVE, apng_delay_t, NULL); consvar_t cv_apng_downscale = CVAR_INIT ("apng_downscale", "On", CV_SAVE, CV_OnOff, NULL); +#ifdef USE_APNG static boolean apng_downscale = false; // So nobody can do something dumb like changing cvars mid output +#endif boolean takescreenshot = false; // Take a screenshot this tic diff --git a/src/m_misc.h b/src/m_misc.h index d23c53978..82ccd58c7 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 1596a87e5..8a99312e6 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -62,7 +62,7 @@ int thinkframe_hooks_capacity = 16; static INT32 draw_row; -void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src) +void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) { if (!thinkframe_hooks) { @@ -565,7 +565,7 @@ void M_DrawPerfStats(void) len = (int)strlen(str); if (len > 20) str += len - 20; - snprintf(s, sizeof s - 1, "%20s: %u", str, thinkframe_hooks[i].time_taken); + snprintf(s, sizeof s - 1, "%20s: %d", str, I_PreciseToMicros(thinkframe_hooks[i].time_taken)); V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s); y += 4; // repeated code! if (y > 192) diff --git a/src/m_perfstats.h b/src/m_perfstats.h index 132bea38c..71208fbc1 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -30,11 +30,11 @@ extern int ps_lua_mobjhooks; typedef struct { - UINT32 time_taken; + precise_t time_taken; char short_src[LUA_IDSIZE]; } ps_hookinfo_t; -void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src); +void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); void M_DrawPerfStats(void); diff --git a/src/m_queue.c b/src/m_queue.c index 8603ab202..a337ca4ce 100644 --- a/src/m_queue.c +++ b/src/m_queue.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2020 by Sonic Team Junior. +// Copyright (C) 2003-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_queue.h b/src/m_queue.h index 3e9579e11..cc64b8dd7 100644 --- a/src/m_queue.h +++ b/src/m_queue.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2020 by Sonic Team Junior. +// Copyright (C) 2003-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_random.c b/src/m_random.c index 481fdb72b..2e6213e12 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -60,7 +60,7 @@ UINT8 M_RandomByte(void) */ INT32 M_RandomKey(INT32 a) { - return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*a); + return (INT32)((rand()/((float)RAND_MAX+1.0f))*a); } /** Provides a random integer in a given range. @@ -73,7 +73,7 @@ INT32 M_RandomKey(INT32 a) */ INT32 M_RandomRange(INT32 a, INT32 b) { - return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*(b-a+1))+a; + return (INT32)((rand()/((float)RAND_MAX+1.0f))*(b-a+1))+a; } diff --git a/src/m_random.h b/src/m_random.h index 01190e046..df10b4bb3 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_swap.h b/src/m_swap.h index b44d6de8c..6aa347d97 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.c b/src/mserv.c index dfb417415..f64c7bea9 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by James R. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.h b/src/mserv.h index d0d5e49df..7a3b3d8ec 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by James R. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_ceilng.c b/src/p_ceilng.c index f12499d5c..43f3cc1d5 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -395,9 +395,8 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) sector_t *sec; ceiling_t *ceiling; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -617,9 +616,8 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type) sector_t *sec; ceiling_t *ceiling; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; diff --git a/src/p_enemy.c b/src/p_enemy.c index 12bba0b4d..6a92c5d33 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,6 +25,7 @@ #include "i_video.h" #include "z_zone.h" #include "lua_hook.h" +#include "m_cond.h" // SECRET_SKIN #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -1708,7 +1709,7 @@ void A_HoodThink(mobj_t *actor) dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z); dm = P_AproxDistance(dx, dy); // Target dangerously close to robohood, retreat then. - if ((dm < 256<flags2 & MF2_AMBUSH)) { S_StartSound(actor, actor->info->attacksound); P_SetMobjState(actor, actor->info->raisestate); @@ -3961,7 +3962,7 @@ void A_BossDeath(mobj_t *mo) } bossjustdie: - if (LUAh_BossDeath(mo)) + if (LUA_HookMobj(mo, MOBJ_HOOK(BossDeath))) return; else if (P_MobjWasRemoved(mo)) return; @@ -4201,7 +4202,7 @@ void A_CustomPower(mobj_t *actor) return; } - if (locvar1 >= NUMPOWERS) + if (locvar1 >= NUMPOWERS || locvar1 < 0) { CONS_Debug(DBG_GAMELOGIC, "Power #%d out of range!\n", locvar1); return; @@ -5101,6 +5102,33 @@ void A_SignSpin(mobj_t *actor) } } +static boolean SignSkinCheck(player_t *player, INT32 num) +{ + INT32 i; + + if (player != NULL) + { + // Use player's availabilities + return R_SkinUsable(player - players, num); + } + + // Player invalid, only show characters that are unlocked from the start. + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (unlockables[i].type == SECRET_SKIN) + { + INT32 lockedSkin = M_UnlockableSkinNum(&unlockables[i]); + + if (lockedSkin == num) + { + return false; + } + } + } + + return true; +} + // Function: A_SignPlayer // // Description: Changes the state of a level end sign to reflect the player that hit it. @@ -5161,23 +5189,21 @@ void A_SignPlayer(mobj_t *actor) // I turned this function into a fucking mess. I'm so sorry. -Lach if (locvar1 == -2) // random skin { -#define skincheck(num) (player ? !R_SkinUsable(player-players, num) : skins[num].availability > 0) player_t *player = actor->target ? actor->target->player : NULL; UINT8 skinnum; UINT8 skincount = 0; for (skinnum = 0; skinnum < numskins; skinnum++) - if (!skincheck(skinnum)) + if (SignSkinCheck(player, skinnum)) skincount++; skinnum = P_RandomKey(skincount); for (skincount = 0; skincount < numskins; skincount++) { if (skincount > skinnum) break; - if (skincheck(skincount)) + if (!SignSkinCheck(player, skincount)) skinnum++; } skin = &skins[skinnum]; -#undef skincheck } else // specific skin skin = &skins[locvar1]; @@ -9873,28 +9899,29 @@ void A_Custom3DRotate(mobj_t *actor) const fixed_t radius = FixedMul(loc1lw*FRACUNIT, actor->scale); const fixed_t hOff = FixedMul(loc1up*FRACUNIT, actor->scale); - const fixed_t hspeed = FixedMul(loc2up*FRACUNIT/10, actor->scale); - const fixed_t vspeed = FixedMul(loc2lw*FRACUNIT/10, actor->scale); + const fixed_t hspeed = loc2up*FRACUNIT/10; // Monster's note (29/05/21): DO NOT SCALE, this is an angular speed! + const fixed_t vspeed = loc2lw*FRACUNIT/10; // ditto if (LUA_CallAction(A_CUSTOM3DROTATE, actor)) return; + if (!actor->target) // Ensure we actually have a target first. + { + CONS_Printf("Error: A_Custom3DRotate: Object has no target.\n"); + P_RemoveMobj(actor); + return; + } + if (actor->target->health == 0) { P_RemoveMobj(actor); return; } - if (!actor->target) // This should NEVER happen. - { - if (cv_debug) - CONS_Printf("Error: Object has no target\n"); - P_RemoveMobj(actor); - return; - } if (hspeed==0 && vspeed==0) { - CONS_Printf("Error: A_Custom3DRotate: Object has no speed.\n"); + if (cv_debug) + CONS_Printf("Error: A_Custom3DRotate: Object has no speed.\n"); return; } @@ -14319,6 +14346,14 @@ void A_RolloutRock(mobj_t *actor) if (LUA_CallAction(A_ROLLOUTROCK, actor)) return; + if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) + actor->flags |= MF_PUSHABLE; + else + { + actor->flags2 = (actor->flags2 & ~MF2_OBJECTFLIP) | (actor->tracer->flags2 & MF2_OBJECTFLIP); + actor->eflags = (actor->eflags & ~MFE_VERTICALFLIP) | (actor->tracer->eflags & MFE_VERTICALFLIP); + } + actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves if (actor->eflags & MFE_JUSTHITFLOOR) @@ -14357,7 +14392,8 @@ void A_RolloutRock(mobj_t *actor) speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling - if (speed < actor->scale >> 1) // stop moving if speed is insignificant + if (((actor->flags & MF_PUSHABLE) || !(actor->flags2 & MF2_STRONGBOX)) + && speed < actor->scale) // stop moving if speed is insignificant { actor->momx = 0; actor->momy = 0; @@ -14377,9 +14413,6 @@ void A_RolloutRock(mobj_t *actor) actor->frame = actor->reactiontime % maxframes; // set frame - if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) - actor->flags |= MF_PUSHABLE; - if (!(actor->flags & MF_PUSHABLE) || (actor->movecount != 1)) // if being ridden or haven't moved, don't disappear actor->fuse = actor->info->painchance; else if (actor->fuse < 2*TICRATE) diff --git a/src/p_floor.c b/src/p_floor.c index 7c26065b5..d81a022e5 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -635,7 +635,6 @@ void T_BounceCheese(bouncecheese_t *bouncer) boolean remove; INT32 i; mtag_t tag = Tag_FGet(&bouncer->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT || bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself! @@ -650,7 +649,7 @@ void T_BounceCheese(bouncecheese_t *bouncer) } // You can use multiple target sectors, but at your own risk!!! - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { actionsector = §ors[i]; actionsector->moved = true; @@ -775,7 +774,6 @@ void T_StartCrumble(crumble_t *crumble) sector_t *sector; INT32 i; mtag_t tag = Tag_FGet(&crumble->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); // Once done, the no-return thinker just sits there, // constantly 'returning'... kind of an oxymoron, isn't it? @@ -804,7 +802,7 @@ void T_StartCrumble(crumble_t *crumble) } else if (++crumble->timer == 0) // Reposition back to original spot { - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; @@ -840,7 +838,7 @@ void T_StartCrumble(crumble_t *crumble) // Flash to indicate that the platform is about to return. if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0)) { - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; @@ -932,7 +930,7 @@ void T_StartCrumble(crumble_t *crumble) P_RemoveThinker(&crumble->thinker); } - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; sector->moved = true; @@ -948,7 +946,6 @@ void T_StartCrumble(crumble_t *crumble) void T_MarioBlock(mariothink_t *block) { INT32 i; - TAG_ITER_DECLARECOUNTER(0); T_MovePlane ( @@ -983,7 +980,7 @@ void T_MarioBlock(mariothink_t *block) block->sector->ceilspeed = 0; block->direction = 0; } - TAG_ITER_SECTORS(0, (INT16)block->tag, i) + TAG_ITER_SECTORS((INT16)block->tag, i) P_RecalcPrecipInSector(§ors[i]); } @@ -1293,9 +1290,8 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) INT32 secnum = -1; boolean FOFsector = false; mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -1306,14 +1302,13 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) { INT32 targetsecnum = -1; mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags); - TAG_ITER_DECLARECOUNTER(1); if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) continue; FOFsector = true; - TAG_ITER_SECTORS(1, tag2, targetsecnum) + TAG_ITER_SECTORS(tag2, targetsecnum) { if (T_SectorHasEnemies(§ors[targetsecnum])) return; @@ -1400,7 +1395,6 @@ void T_EachTimeThinker(eachtime_t *eachtime) fixed_t bottomheight, topheight; ffloor_t *rover; mtag_t tag = Tag_FGet(&eachtime->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); for (i = 0; i < MAXPLAYERS; i++) { @@ -1410,7 +1404,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) eachtime->playersOnArea[i] = false; } - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -1428,14 +1422,13 @@ void T_EachTimeThinker(eachtime_t *eachtime) { INT32 targetsecnum = -1; mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags); - TAG_ITER_DECLARECOUNTER(1); if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) continue; FOFsector = true; - TAG_ITER_SECTORS(1, tag2, targetsecnum) + TAG_ITER_SECTORS(tag2, targetsecnum) { targetsec = §ors[targetsecnum]; @@ -1570,12 +1563,11 @@ void T_RaiseSector(raise_t *raise) INT32 direction; result_e res = 0; mtag_t tag = raise->tag; - TAG_ITER_DECLARECOUNTER(0); if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata) return; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; @@ -1702,7 +1694,7 @@ void T_RaiseSector(raise_t *raise) raise->sector->ceilspeed = 42; raise->sector->floorspeed = speed*direction; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) P_RecalcPrecipInSector(§ors[i]); } @@ -1820,9 +1812,8 @@ void EV_DoFloor(line_t *line, floor_e floortype) sector_t *sec; floormove_t *dofloor; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -2037,10 +2028,9 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) sector_t *sec; elevator_t *elevator; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); // act on all sectors with the same tag as the triggering linedef - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -2337,7 +2327,6 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, sector_t *foundsec; INT32 i; mtag_t tag = Tag_FGet(&rover->master->tags); - TAG_ITER_DECLARECOUNTER(0); // If floor is already activated, skip it if (sec->floordata) @@ -2380,7 +2369,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, crumble->sector->crumblestate = CRUMBLE_ACTIVATED; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { foundsec = §ors[i]; diff --git a/src/p_inter.c b/src/p_inter.c index e9a16a3dd..89989d1af 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -365,7 +365,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->flags & (MF_ENEMY|MF_BOSS) && special->flags2 & MF2_FRET) return; - if (LUAh_TouchSpecial(special, toucher) || P_MobjWasRemoved(special)) + if (LUA_HookTouchSpecial(special, toucher) || P_MobjWasRemoved(special)) return; // 0 = none, 1 = elemental pierce, 2 = bubble bounce @@ -1939,7 +1939,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour if (!netgame) return; // Presumably it's obvious what's happening in splitscreen. - if (LUAh_HurtMsg(player, inflictor, source, damagetype)) + if (LUA_HookHurtMsg(player, inflictor, source, damagetype)) return; deadtarget = (player->mo->health <= 0); @@ -2413,7 +2413,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL); target->health = 0; // This makes it easy to check if something's dead elsewhere. - if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target)) return; // Let EVERYONE know what happened to a player! 01-29-2002 Tails @@ -3548,7 +3548,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Everything above here can't be forced. if (!metalrecording) { - UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage, damagetype); + UINT8 shouldForce = LUA_HookShouldDamage(target, inflictor, source, damage, damagetype); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed if (shouldForce == 1) @@ -3589,7 +3589,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force && target->flags2 & MF2_FRET) // Currently flashing from being hit return false; - if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) return true; if (target->health > 1) @@ -3639,7 +3639,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da || (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam))) return false; // Don't run eachother over in special stages and team games and such } - if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) + if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) return true; P_NiGHTSDamage(target, source); // -5s :( return true; @@ -3693,13 +3693,13 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (force || (inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE)) // Super Sonic is stunned! { - if (!LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) + if (!LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) P_SuperDamage(player, inflictor, source, damage); return true; } return false; } - else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) + else if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) return true; else if (player->powers[pw_shield] || (player->bot && !ultimatemode)) //If One-Hit Shield { diff --git a/src/p_lights.c b/src/p_lights.c index d396e92d3..1e41146da 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -374,10 +374,9 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force) { INT32 i; - TAG_ITER_DECLARECOUNTER(0); // search all sectors for ones with tag - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { if (!force && ticbased // always let speed fader execute && sectors[i].lightingdata diff --git a/src/p_local.h b/src/p_local.h index 8caab0d27..1fcd3050d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -143,6 +143,8 @@ angle_t P_GetLocalAngle(player_t *player); void P_SetLocalAngle(player_t *player, angle_t angle); void P_ForceLocalAngle(player_t *player, angle_t angle); boolean P_PlayerFullbright(player_t *player); +boolean P_PlayerCanEnterSpinGaps(player_t *player); +boolean P_PlayerShouldUseSpinHeight(player_t *player); boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo); diff --git a/src/p_map.c b/src/p_map.c index a1cad524e..e55bebb9a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -419,16 +419,23 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } else if (object->player->dashmode >= DASHMODE_THRESHOLD) P_SetPlayerMobjState(object, S_PLAY_DASH); - else if (P_IsObjectOnGround(object) && horizspeed >= FixedMul(object->player->runspeed, object->scale)) - P_SetPlayerMobjState(object, S_PLAY_RUN); + else if (P_IsObjectOnGround(object)) + P_SetPlayerMobjState(object, (horizspeed >= FixedMul(object->player->runspeed, object->scale)) ? S_PLAY_RUN : S_PLAY_WALK); else - P_SetPlayerMobjState(object, S_PLAY_WALK); + P_SetPlayerMobjState(object, (object->momz > 0) ? S_PLAY_SPRING : S_PLAY_FALL); } else if (P_MobjFlip(object)*vertispeed > 0) P_SetPlayerMobjState(object, S_PLAY_SPRING); else P_SetPlayerMobjState(object, S_PLAY_FALL); } + else if (horizspeed + && object->tracer + && object->tracer->player + && object->tracer->player->powers[pw_carry] != CR_NONE + && object->tracer->tracer == object + && (!demoplayback || P_ControlStyle(object->tracer->player) == CS_LMAOGALOG)) + P_SetPlayerAngle(object->tracer->player, spring->angle); object->standingslope = NULL; // And again. @@ -511,6 +518,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) if (spring->state != &states[S_STEAM1]) // Only when it bursts break; + object->eflags |= MFE_SPRUNG; object->momz = flipval*FixedMul(speed, FixedSqrt(FixedMul(spring->scale, object->scale))); // scale the speed with both objects' scales, just like with springs! if (p) @@ -746,7 +754,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // underneath // REX HAS SEEN YOU - if (!LUAh_SeenPlayer(tmthing->target->player, thing->player)) + if (!LUA_HookSeenPlayer(tmthing->target->player, thing->player)) return false; seenplayer = thing->player; @@ -935,7 +943,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } { - UINT8 shouldCollide = LUAh_MobjCollide(thing, tmthing); // checks hook for thing's type + UINT8 shouldCollide = LUA_Hook2Mobj(thing, tmthing, MOBJ_HOOK(MobjCollide)); // checks hook for thing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -943,7 +951,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (shouldCollide == 2) return true; // force no collide - shouldCollide = LUAh_MobjMoveCollide(tmthing, thing); // checks hook for tmthing's type + shouldCollide = LUA_Hook2Mobj(tmthing, thing, MOBJ_HOOK(MobjMoveCollide)); // checks hook for tmthing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -1927,7 +1935,7 @@ static boolean PIT_CheckLine(line_t *ld) blockingline = ld; { - UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, blockingline); // checks hook for thing's type + UINT8 shouldCollide = LUA_HookMobjLineCollide(tmthing, blockingline); // checks hook for thing's type if (P_MobjWasRemoved(tmthing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -2723,7 +2731,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->type == MT_SKIM) maxstep = 0; - if (tmceilingz - tmfloorz < thing->height) + if (tmceilingz - tmfloorz < thing->height + || (thing->player + && tmceilingz - tmfloorz < P_GetPlayerHeight(thing->player) + && !P_PlayerCanEnterSpinGaps(thing->player))) { if (tmfloorthing) tmhitthing = tmfloorthing; @@ -3331,6 +3342,11 @@ static boolean PTR_LineIsBlocking(line_t *li) if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale)) return true; // too big a step up + if (slidemo->player + && openrange < P_GetPlayerHeight(slidemo->player) + && !P_PlayerCanEnterSpinGaps(slidemo->player)) + return true; // nonspin character should not take this path + return false; } diff --git a/src/p_maputl.c b/src/p_maputl.c index 90718a41c..efcebe736 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_maputl.h b/src/p_maputl.h index 08b606833..cec344d03 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_mobj.c b/src/p_mobj.c index 49db6daee..10220fff6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1844,7 +1844,7 @@ void P_XYMovement(mobj_t *mo) B_MoveBlocked(player); } - if (LUAh_MobjMoveBlocked(mo)) + if (LUA_HookMobj(mo, MOBJ_HOOK(MobjMoveBlocked))) { if (P_MobjWasRemoved(mo)) return; @@ -3286,11 +3286,9 @@ void P_MobjCheckWater(mobj_t *mobj) boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC); if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER) && !(mobj->eflags & MFE_TOUCHLAVA))) { // Water removes electric and non-water fire shields... - P_FlashPal(p, - electric - ? PAL_WHITE - : PAL_NUKE, - 1); + if (electric) + P_FlashPal(p, PAL_WHITE, 1); + p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; } } @@ -4607,9 +4605,8 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta) INT32 snum; sector_t *sector; boolean gotcage = false; - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, snum) + TAG_ITER_SECTORS(tag, snum) { sector = §ors[snum]; sector->floorheight += delta; @@ -4693,9 +4690,8 @@ static void P_Boss4DestroyCage(mobj_t *mobj) size_t a; sector_t *sector, *rsec; ffloor_t *rover; - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, snum) + TAG_ITER_SECTORS(tag, snum) { sector = §ors[snum]; @@ -7512,7 +7508,7 @@ static void P_RosySceneryThink(mobj_t *mobj) static void P_MobjSceneryThink(mobj_t *mobj) { - if (LUAh_MobjThinker(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker))) return; if (P_MobjWasRemoved(mobj)) return; @@ -7860,7 +7856,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) if (!mobj->fuse) { - if (!LUAh_MobjFuse(mobj)) + if (!LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse))) P_RemoveMobj(mobj); return; } @@ -7919,7 +7915,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) mobj->fuse--; if (!mobj->fuse) { - if (!LUAh_MobjFuse(mobj)) + if (!LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse))) P_RemoveMobj(mobj); return; } @@ -7948,7 +7944,7 @@ static boolean P_MobjPushableThink(mobj_t *mobj) static boolean P_MobjBossThink(mobj_t *mobj) { - if (LUAh_BossThinker(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(BossThinker))) { if (P_MobjWasRemoved(mobj)) return false; @@ -9875,7 +9871,7 @@ static boolean P_FuseThink(mobj_t *mobj) if (mobj->fuse) return true; - if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse)) || P_MobjWasRemoved(mobj)) ; else if (mobj->info->flags & MF_MONITOR) { @@ -10051,13 +10047,13 @@ void P_MobjThinker(mobj_t *mobj) // Check for a Lua thinker first if (!mobj->player) { - if (LUAh_MobjThinker(mobj) || P_MobjWasRemoved(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker)) || P_MobjWasRemoved(mobj)) return; } else if (!mobj->player->spectator) { // You cannot short-circuit the player thinker like you can other thinkers. - LUAh_MobjThinker(mobj); + LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker)); if (P_MobjWasRemoved(mobj)) return; } @@ -10525,7 +10521,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks! - if (LUAh_MobjSpawn(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjSpawn))) { if (P_MobjWasRemoved(mobj)) return NULL; @@ -10912,7 +10908,7 @@ void P_RemoveMobj(mobj_t *mobj) return; // something already removing this mobj. mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. - LUAh_MobjRemoved(mobj); + LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved)); mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work. // Rings only, please! @@ -11964,6 +11960,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) INT32 j; emblem_t* emblem = M_GetLevelEmblems(gamemap); skincolornum_t emcolor; + boolean validEmblem = true; while (emblem) { @@ -11988,8 +11985,19 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting mobj->color = (UINT16)emcolor; - if (emblemlocations[j].collected - || (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin)) + validEmblem = !emblemlocations[j].collected; + + if (emblemlocations[j].type == ET_SKIN) + { + INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]); + + if (players[0].skin != skinnum) + { + validEmblem = false; + } + } + + if (validEmblem == false) { P_UnsetThingPosition(mobj); mobj->flags |= MF_NOCLIP; @@ -12562,7 +12570,7 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) { - boolean override = LUAh_MapThingSpawn(mobj, mthing); + boolean override = LUA_HookMapThingSpawn(mobj, mthing); if (P_MobjWasRemoved(mobj)) return false; diff --git a/src/p_mobj.h b/src/p_mobj.h index 5bb7c908e..82cd056a8 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 874edbd50..6431e4624 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 8c2946965..7c814e0bf 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_pspr.h b/src/p_pspr.h index 231262beb..4525ba14c 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_saveg.c b/src/p_saveg.c index 03229e740..770c641b9 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -64,12 +64,29 @@ typedef enum static inline void P_ArchivePlayer(void) { const player_t *player = &players[consoleplayer]; - INT16 skininfo = player->skin + (botskin<<5); SINT8 pllives = player->lives; if (pllives < startinglivesbalance[numgameovers]) // Bump up to 3 lives if the player pllives = startinglivesbalance[numgameovers]; // has less than that. - WRITEUINT16(save_p, skininfo); +#ifdef NEWSKINSAVES + // Write a specific value into the old skininfo location. + // If we read something other than this, it's an older save file that used skin numbers. + WRITEUINT16(save_p, NEWSKINSAVES); +#endif + + // Write skin names, so that loading skins in different orders + // doesn't change who the save file is for! + WRITESTRINGN(save_p, skins[player->skin].name, SKINNAMESIZE); + + if (botskin != 0) + { + WRITESTRINGN(save_p, skins[botskin-1].name, SKINNAMESIZE); + } + else + { + WRITESTRINGN(save_p, "\0", SKINNAMESIZE); + } + WRITEUINT8(save_p, numgameovers); WRITESINT8(save_p, pllives); WRITEUINT32(save_p, player->score); @@ -78,9 +95,27 @@ static inline void P_ArchivePlayer(void) static inline void P_UnArchivePlayer(void) { - INT16 skininfo = READUINT16(save_p); - savedata.skin = skininfo & ((1<<5) - 1); - savedata.botskin = skininfo >> 5; +#ifdef NEWSKINSAVES + INT16 backwardsCompat = READUINT16(save_p); + + if (backwardsCompat != NEWSKINSAVES) + { + // This is an older save file, which used direct skin numbers. + savedata.skin = backwardsCompat & ((1<<5) - 1); + savedata.botskin = backwardsCompat >> 5; + } + else +#endif + { + char ourSkinName[SKINNAMESIZE+1]; + char botSkinName[SKINNAMESIZE+1]; + + READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); + savedata.skin = R_SkinAvailable(ourSkinName); + + READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + savedata.botskin = R_SkinAvailable(botSkinName) + 1; + } savedata.numgameovers = READUINT8(save_p); savedata.lives = READSINT8(save_p); @@ -4190,7 +4225,10 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) tokenlist = READUINT32(save_p); if (!P_LoadLevel(true, reloading)) + { + CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); return false; + } // get the time leveltime = READUINT32(save_p); @@ -4268,19 +4306,26 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void) { switch (READUINT8(save_p)) { - case 0xb7: + case 0xb7: // luabanks marker { UINT8 i, banksinuse = READUINT8(save_p); if (banksinuse > NUM_LUABANKS) + { + CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n")); return false; + } for (i = 0; i < banksinuse; i++) luabanks[i] = READINT32(save_p); - if (READUINT8(save_p) != 0x1d) + if (READUINT8(save_p) != 0x1d) // consistency marker + { + CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n")); return false; + } } - case 0x1d: + case 0x1d: // consistency marker break; - default: + default: // anything else is nonsense + CONS_Alert(CONS_ERROR, M_GetText("Failed consistency check (???)\n")); return false; } diff --git a/src/p_saveg.h b/src/p_saveg.h index be98953eb..a909282fe 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,6 +18,8 @@ #pragma interface #endif +#define NEWSKINSAVES (INT16_MAX) // Purely for backwards compatibility, remove this for 2.3 + // Persistent storage/archiving. // These are the load / save game routines. diff --git a/src/p_setup.c b/src/p_setup.c index d1c0f1740..068d1d487 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -65,7 +65,7 @@ #include "md5.h" // map MD5 -// for LUAh_MapLoad +// for MapLoad hook #include "lua_script.h" #include "lua_hook.h" @@ -2486,7 +2486,7 @@ static void P_LoadMapBSP(const virtres_t *virt) if (numsubsectors <= 0) I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); if (numnodes <= 0) - I_Error("Level has no nodes"); + I_Error("Level has no nodes (does your map have at least 2 sectors?)"); if (numsegs <= 0) I_Error("Level has no segs"); @@ -2950,6 +2950,75 @@ static void P_LinkMapData(void) } } +// For maps in binary format, add multi-tags from linedef specials. This must be done +// before any linedef specials have been processed. +static void P_AddBinaryMapTagsFromLine(sector_t *sector, line_t *line) +{ + Tag_Add(§or->tags, Tag_FGet(&line->tags)); + if (line->flags & ML_EFFECT6) { + if (sides[line->sidenum[0]].textureoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].textureoffset / FRACUNIT); + if (sides[line->sidenum[0]].rowoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].rowoffset / FRACUNIT); + } + if (line->flags & ML_TFERLINE) { + if (sides[line->sidenum[1]].textureoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].textureoffset / FRACUNIT); + if (sides[line->sidenum[1]].rowoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].rowoffset / FRACUNIT); + } +} + +static void P_AddBinaryMapTags(void) +{ + size_t i; + + for (i = 0; i < numlines; i++) + { + // 96: Apply Tag to Tagged Sectors + // 97: Apply Tag to Front Sector + // 98: Apply Tag to Back Sector + // 99: Apply Tag to Front and Back Sectors + if (lines[i].special == 96) { + size_t j; + mtag_t tag = Tag_FGet(&lines[i].frontsector->tags); + mtag_t target_tag = Tag_FGet(&lines[i].tags); + mtag_t offset_tags[4]; + memset(offset_tags, 0, sizeof(mtag_t)*4); + if (lines[i].flags & ML_EFFECT6) { + offset_tags[0] = (INT32)sides[lines[i].sidenum[0]].textureoffset / FRACUNIT; + offset_tags[1] = (INT32)sides[lines[i].sidenum[0]].rowoffset / FRACUNIT; + } + if (lines[i].flags & ML_TFERLINE) { + offset_tags[2] = (INT32)sides[lines[i].sidenum[1]].textureoffset / FRACUNIT; + offset_tags[3] = (INT32)sides[lines[i].sidenum[1]].rowoffset / FRACUNIT; + } + + for (j = 0; j < numsectors; j++) { + boolean matches_target_tag = target_tag && Tag_Find(§ors[j].tags, target_tag); + size_t k; for (k = 0; k < 4; k++) { + if (lines[i].flags & ML_EFFECT5) { + if (matches_target_tag || (offset_tags[k] && Tag_Find(§ors[j].tags, offset_tags[k]))) { + Tag_Add(§ors[j].tags, tag); + break; + } + } else if (matches_target_tag) { + if (k == 0) + Tag_Add(§ors[j].tags, tag); + if (offset_tags[k]) + Tag_Add(§ors[j].tags, offset_tags[k]); + } + } + } + } else { + if (lines[i].special == 97 || lines[i].special == 99) + P_AddBinaryMapTagsFromLine(lines[i].frontsector, &lines[i]); + if (lines[i].special == 98 || lines[i].special == 99) + P_AddBinaryMapTagsFromLine(lines[i].backsector, &lines[i]); + } + } +} + //For maps in binary format, converts setup of specials to UDMF format. static void P_ConvertBinaryMap(void) { @@ -2966,9 +3035,7 @@ static void P_ConvertBinaryMap(void) INT32 check = -1; INT32 paramline = -1; - TAG_ITER_DECLARECOUNTER(0); - - TAG_ITER_LINES(0, tag, check) + TAG_ITER_LINES(tag, check) { if (lines[check].special == 22) { @@ -3141,6 +3208,34 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = tag; lines[i].special = 720; break; + case 723: //Copy back side floor slope + case 724: //Copy back side ceiling slope + case 725: //Copy back side floor and ceiling slope + if (lines[i].special != 724) + lines[i].args[2] = tag; + if (lines[i].special != 723) + lines[i].args[3] = tag; + lines[i].special = 720; + break; + case 730: //Copy front side floor slope to back side + case 731: //Copy front side ceiling slope to back side + case 732: //Copy front side floor and ceiling slope to back side + if (lines[i].special != 731) + lines[i].args[4] |= TMSC_FRONTTOBACKFLOOR; + if (lines[i].special != 730) + lines[i].args[4] |= TMSC_FRONTTOBACKCEILING; + lines[i].special = 720; + break; + case 733: //Copy back side floor slope to front side + case 734: //Copy back side ceiling slope to front side + case 735: //Copy back side floor and ceiling slope to front side + if (lines[i].special != 734) + lines[i].args[4] |= TMSC_BACKTOFRONTFLOOR; + if (lines[i].special != 733) + lines[i].args[4] |= TMSC_BACKTOFRONTCEILING; + lines[i].special = 720; + break; + case 900: //Translucent wall (10%) case 901: //Translucent wall (20%) case 902: //Translucent wall (30%) @@ -3183,11 +3278,9 @@ static void P_ConvertBinaryMap(void) INT32 firstline = -1; mtag_t tag = mapthings[i].angle; - TAG_ITER_DECLARECOUNTER(0); - Tag_FSet(&mapthings[i].tags, tag); - TAG_ITER_LINES(0, tag, check) + TAG_ITER_LINES(tag, check) { if (lines[check].special == 20) { @@ -3287,6 +3380,9 @@ static boolean P_LoadMapFromFile(void) P_LinkMapData(); + if (!udmf) + P_AddBinaryMapTags(); + Taglist_InitGlobalTables(); if (!udmf) @@ -3394,8 +3490,10 @@ static void P_InitLevelSettings(void) numstarposts = 0; ssspheres = timeinmap = 0; - // special stage - stagefailed = true; // assume failed unless proven otherwise - P_GiveEmerald or emerald touchspecial + // Assume Special Stages were failed in unless proven otherwise - via P_GiveEmerald or emerald touchspecial + // Normal stages will default to be OK, until a Lua script / linedef executor says otherwise. + stagefailed = G_IsSpecialStage(gamemap); + // Reset temporary record data memset(&ntemprecords, 0, sizeof(nightsdata_t)); @@ -4135,7 +4233,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) #ifdef HWRENDER // Free GPU textures before freeing patches. - if (vid.glstate == VID_GL_LIBRARY_LOADED) + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) HWR_ClearAllTextures(); #endif @@ -4174,7 +4272,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_ResetWaypoints(); - P_MapStart(); + P_MapStart(); // tmthing can be used starting from this point if (!P_LoadMapFromFile()) return false; @@ -4227,8 +4325,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // clear special respawning que iquehead = iquetail = 0; - P_MapEnd(); - // Remove the loading shit from the screen if (rendermode != render_none && !(titlemapinaction || reloadinggamestate)) F_WipeColorFill(levelfadecol); @@ -4248,6 +4344,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_RunCachedActions(); + P_MapEnd(); // tmthing is no longer needed from this point onwards + // Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap... if (!titlemapinaction) { @@ -4271,7 +4369,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); } P_PreTicker(2); - LUAh_MapLoad(); + P_MapStart(); // just in case MapLoad modifies tmthing + LUA_HookInt(gamemap, HOOK(MapLoad)); + P_MapEnd(); // just in case MapLoad modifies tmthing } // No render mode or reloading gamestate, stop here. @@ -4491,7 +4591,7 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) #ifdef HWRENDER // Free GPU textures before freeing patches. - if (vid.glstate == VID_GL_LIBRARY_LOADED) + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) HWR_ClearAllTextures(); #endif @@ -4518,8 +4618,8 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) // // look for skins // - R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] - R_PatchSkins(wadnum); // toast: PATCH PATCH + R_AddSkins(wadnum, false); // faB: wadfile index in wadfiles[] + R_PatchSkins(wadnum, false); // toast: PATCH PATCH ST_ReloadSkinFaceGraphics(); // diff --git a/src/p_setup.h b/src/p_setup.h index ae849acbf..c3c680fdd 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_sight.c b/src/p_sight.c index 2e1e49997..706745f35 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -307,7 +307,7 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) for (rover = front->ffloors; rover; rover = rover->next) { if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT) + || !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG))) { continue; } @@ -323,7 +323,7 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) for (rover = back->ffloors; rover; rover = rover->next) { if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT) + || !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG))) { continue; } @@ -452,7 +452,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) /// \todo Improve by checking fog density/translucency /// and setting a sight limit. if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERPLANES) || rover->flags & FF_TRANSLUCENT) + || !(rover->flags & FF_RENDERPLANES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG))) { continue; } diff --git a/src/p_slopes.c b/src/p_slopes.c index aa46a8402..4e93e4a45 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2020 by Sonic Team Junior. +// Copyright (C) 2015-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -546,11 +546,10 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling) { INT32 i; pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope; - TAG_ITER_DECLARECOUNTER(0); if (!tag || *secslope) return false; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope; if (srcslope) @@ -774,13 +773,13 @@ void P_SlopeLaunch(mobj_t *mo) mo->momx = slopemom.x; mo->momy = slopemom.y; mo->momz = slopemom.z/2; + + if (mo->player) + mo->player->powers[pw_justlaunched] = 1; } //CONS_Printf("Launched off of slope.\n"); mo->standingslope = NULL; - - if (mo->player) - mo->player->powers[pw_justlaunched] = 1; } // diff --git a/src/p_slopes.h b/src/p_slopes.h index 46e8dc1e7..ae040ae56 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2020 by Sonic Team Junior. +// Copyright (C) 2015-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_spec.c b/src/p_spec.c index 226e58d15..4b566acfb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,7 +35,7 @@ #include "v_video.h" // V_AUTOFADEOUT|V_ALLOWLOWERCASE #include "m_misc.h" #include "m_cond.h" //unlock triggers -#include "lua_hook.h" // LUAh_LinedefExecute +#include "lua_hook.h" // LUA_HookLinedefExecute #include "f_finale.h" // control text prompt #include "r_skins.h" // skins @@ -2223,7 +2223,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT32 secnum = -1; mobj_t *bot = NULL; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid! @@ -2251,7 +2250,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) newceilinglightsec = line->frontsector->ceilinglightsec; // act on all sectors with the same tag as the triggering linedef - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (sectors[secnum].lightingdata) { @@ -2306,7 +2305,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 409: // Change tagged sectors' tag // (formerly "Change calling sectors' tag", but behavior was changed) { - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) Tag_SectorFSet(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); break; } @@ -2316,7 +2315,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 411: // Stop floor/ceiling movement in tagged sector(s) - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (sectors[secnum].floordata) { @@ -2501,7 +2500,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Additionally play the sound from tagged sectors' soundorgs sector_t *sec; - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; S_StartSound(&sec->soundorg, sfxnum); @@ -2616,7 +2615,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 416: // Spawn adjustable fire flicker - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2650,7 +2649,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 417: // Spawn adjustable glowing light - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2684,7 +2683,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 418: // Spawn adjustable strobe flash (unsynchronized) - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2718,7 +2717,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 419: // Spawn adjustable strobe flash (synchronized) - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2766,7 +2765,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 421: // Stop lighting effect in tagged sectors - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) if (sectors[secnum].lightingdata) { P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); @@ -2980,7 +2979,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ffloor_t *rover; // FOF that we are going to crumble boolean foundrover = false; // for debug, "Can't find a FOF" message - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3105,7 +3104,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->sidenum[1] != 0xffff) state = (statenum_t)sides[line->sidenum[1]].toptexture; - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { boolean tryagain; sec = sectors + secnum; @@ -3135,7 +3134,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 443: // Calls a named Lua function if (line->stringargs[0]) - LUAh_LinedefExecute(line, mo, callsec); + LUA_HookLinedefExecute(line, mo, callsec); else CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in arg0str)\n", sizeu1(line-lines)); break; @@ -3165,7 +3164,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) boolean foundrover = false; // for debug, "Can't find a FOF" message ffloortype_e oldflags; // store FOF's old flags - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3223,7 +3222,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_NOCLIMB) // don't respawn! respawn = false; - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3279,7 +3278,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) source = sectors[sourcesec].extra_colormap; } } - TAG_ITER_SECTORS(0, line->args[0], secnum) + TAG_ITER_SECTORS(line->args[0], secnum) { if (sectors[secnum].colormap_protected) continue; @@ -3414,7 +3413,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3478,7 +3477,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) boolean foundrover = false; // for debug, "Can't find a FOF" message size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3563,7 +3562,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3614,7 +3613,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } } - TAG_ITER_SECTORS(0, line->args[0], secnum) + TAG_ITER_SECTORS(line->args[0], secnum) { extracolormap_t *source_exc, *dest_exc, *exc; @@ -3694,7 +3693,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } case 456: // Stop fade colormap - TAG_ITER_SECTORS(0, line->args[0], secnum) + TAG_ITER_SECTORS(line->args[0], secnum) P_ResetColormapFader(§ors[secnum]); break; @@ -3887,12 +3886,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 465: // Set linedef executor delay { INT32 linenum; - TAG_ITER_DECLARECOUNTER(1); if (!udmf) break; - TAG_ITER_LINES(1, line->args[0], linenum) + TAG_ITER_LINES(line->args[0], linenum) { if (line->args[2]) lines[linenum].executordelay += line->args[1]; @@ -3902,6 +3900,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 466: // Set level failure state + { + if (line->flags & ML_NOCLIMB) + { + stagefailed = false; + CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); + } + else + { + stagefailed = true; + CONS_Debug(DBG_GAMELOGIC, "Stage will end in failure...\n"); + } + } + break; + case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing PolyDoor(line); @@ -5928,9 +5941,8 @@ void T_LaserFlash(laserthink_t *flash) sector_t *sector; sector_t *sourcesec = flash->sourceline->frontsector; fixed_t top, bottom; - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, flash->tag, s) + TAG_ITER_SECTORS(flash->tag, s) { sector = §ors[s]; for (fflr = sector->ffloors; fflr; fflr = fflr->next) @@ -6210,11 +6222,10 @@ void P_SpawnSpecials(boolean fromnetsave) INT32 s; size_t sec; ffloortype_e ffloorflags; - TAG_ITER_DECLARECOUNTER(0); case 1: // Definable gravity per sector sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) { sectors[s].gravity = §ors[sec].floorheight; // This allows it to change in realtime! @@ -6238,7 +6249,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 5: // Change camera info sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); break; @@ -6265,7 +6276,7 @@ void P_SpawnSpecials(boolean fromnetsave) P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs); else { - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs); } } @@ -6276,7 +6287,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 8: // Sector Parameters - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) { if (lines[i].flags & ML_NOCLIMB) { @@ -6303,7 +6314,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 10: // Vertical culling plane for sprites and FOFs - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].cullheight = &lines[i]; // This allows it to change in realtime! break; @@ -6364,19 +6375,19 @@ void P_SpawnSpecials(boolean fromnetsave) case 63: // support for drawn heights coming from different sector sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].heightsec = (INT32)sec; break; case 64: // Appearing/Disappearing FOF option if (lines[i].flags & ML_BLOCKMONSTERS) { // Find FOFs by control sector tag - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) for (j = 0; (unsigned)j < sectors[s].linecount; j++) if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i); } else // Find FOFs by effect sector tag { - TAG_ITER_LINES(0, tag, s) + TAG_ITER_LINES(tag, s) { if ((size_t)s == i) continue; @@ -6387,15 +6398,15 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 66: // Displace floor by front sector - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; case 67: // Displace ceiling by front sector - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; case 68: // Displace both floor AND ceiling by front sector - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; @@ -6991,46 +7002,46 @@ void P_SpawnSpecials(boolean fromnetsave) case 600: // floor lighting independently (e.g. lava) sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].floorlightsec = (INT32)sec; break; case 601: // ceiling lighting independently sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].ceilinglightsec = (INT32)sec; break; case 602: // Adjustable pulsating light sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableGlowingLight(§ors[sec], §ors[s], P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 603: // Adjustable flickering light sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableFireFlicker(§ors[sec], §ors[s], P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 604: // Adjustable Blinking Light (unsynchronized) sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false); break; case 605: // Adjustable Blinking Light (synchronized) sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true); break; case 606: // HACK! Copy colormaps. Just plain colormaps. - TAG_ITER_SECTORS(0, lines[i].args[0], s) + TAG_ITER_SECTORS(lines[i].args[0], s) { extracolormap_t *exc; @@ -7104,13 +7115,12 @@ void P_SpawnSpecials(boolean fromnetsave) */ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) { - TAG_ITER_DECLARECOUNTER(0); INT32 s; mtag_t tag = Tag_FGet(&lines[line].tags); size_t sec = sides[*lines[line].sidenum].sector-sectors; line_t* li = lines + line; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddFakeFloor(§ors[s], §ors[sec], li, ffloorflags, secthinkers); } @@ -7220,7 +7230,6 @@ void T_Scroll(scroll_t *s) size_t i; INT32 sect; ffloor_t *rover; - TAG_ITER_DECLARECOUNTER(0); case sc_side: // scroll wall texture side = sides + s->affectee; @@ -7257,7 +7266,7 @@ void T_Scroll(scroll_t *s) if (!is3dblock) continue; - TAG_ITER_SECTORS(0, Tag_FGet(&line->tags), sect) + TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) { sector_t *psec; psec = sectors + sect; @@ -7332,7 +7341,7 @@ void T_Scroll(scroll_t *s) if (!is3dblock) continue; - TAG_ITER_SECTORS(0, Tag_FGet(&line->tags), sect) + TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) { sector_t *psec; psec = sectors + sect; @@ -7472,11 +7481,10 @@ static void P_SpawnScrollers(void) switch (special) { register INT32 s; - TAG_ITER_DECLARECOUNTER(0); case 513: // scroll effect ceiling case 533: // scroll and carry objects on ceiling - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_ceiling, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); if (special != 533) break; @@ -7485,13 +7493,13 @@ static void P_SpawnScrollers(void) case 523: // carry objects on ceiling dx = FixedMul(dx, CARRYFACTOR); dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_carry_ceiling, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); break; case 510: // scroll effect floor case 530: // scroll and carry objects on floor - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_floor, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); if (special != 530) break; @@ -7500,7 +7508,7 @@ static void P_SpawnScrollers(void) case 520: // carry objects on floor dx = FixedMul(dx, CARRYFACTOR); dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_carry, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); break; @@ -7508,7 +7516,7 @@ static void P_SpawnScrollers(void) // (same direction and speed as scrolling floors) case 502: { - TAG_ITER_LINES(0, tag, s) + TAG_ITER_LINES(tag, s) if (s != (INT32)i) { if (l->flags & ML_EFFECT2) // use texture offsets instead @@ -7610,9 +7618,8 @@ void T_Disappear(disappear_t *d) ffloor_t *rover; register INT32 s; mtag_t afftag = Tag_FGet(&lines[d->affectee].tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, afftag, s) + TAG_ITER_SECTORS(afftag, s) { for (rover = sectors[s].ffloors; rover; rover = rover->next) { @@ -8343,7 +8350,6 @@ static void P_SpawnFriction(void) fixed_t strength; // frontside texture offset controls magnitude fixed_t friction; // friction value to be applied during movement INT32 movefactor; // applied to each player move to simulate inertia - TAG_ITER_DECLARECOUNTER(0); for (i = 0; i < numlines; i++, l++) if (l->special == 540) @@ -8369,7 +8375,7 @@ static void P_SpawnFriction(void) else movefactor = FRACUNIT; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Friction(friction, movefactor, s, -1); } } @@ -8458,6 +8464,9 @@ static inline boolean PIT_PushThing(mobj_t *thing) if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) return false; + if (!tmpusher->source) + return false; + // Allow this to affect pushable objects at some point? if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->powers[pw_carry] == CR_NIGHTSMODE)) { @@ -8888,7 +8897,6 @@ static void P_SpawnPushers(void) mtag_t tag; register INT32 s; mobj_t *thing; - TAG_ITER_DECLARECOUNTER(0); for (i = 0; i < numlines; i++, l++) { @@ -8896,15 +8904,15 @@ static void P_SpawnPushers(void) switch (l->special) { case 541: // wind - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_wind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 544: // current - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_current, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 547: // push/pull - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) { thing = P_GetPushThing(s); if (thing) // No MT_P* means no effect @@ -8912,19 +8920,19 @@ static void P_SpawnPushers(void) } break; case 545: // current up - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_upcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 546: // current down - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_downcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 542: // wind up - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_upwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 543: // wind down - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; } diff --git a/src/p_spec.h b/src/p_spec.h index bba7c4a40..3b8abfcf8 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_telept.c b/src/p_telept.c index f6feddf4b..6bac5ad20 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_tick.c b/src/p_tick.c index c0a1c5700..d7357eb82 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -656,7 +656,7 @@ void P_Ticker(boolean run) ps_lua_mobjhooks = 0; ps_checkposition_calls = 0; - LUAh_PreThinkFrame(); + LUA_HOOK(PreThinkFrame); ps_playerthink_time = I_GetPreciseTime(); for (i = 0; i < MAXPLAYERS; i++) @@ -687,7 +687,7 @@ void P_Ticker(boolean run) P_PlayerAfterThink(&players[i]); ps_lua_thinkframe_time = I_GetPreciseTime(); - LUAh_ThinkFrame(); + LUA_HookThinkFrame(); ps_lua_thinkframe_time = I_GetPreciseTime() - ps_lua_thinkframe_time; } @@ -760,7 +760,7 @@ void P_Ticker(boolean run) if (modeattacking) G_GhostTicker(); - LUAh_PostThinkFrame(); + LUA_HOOK(PostThinkFrame); } P_MapEnd(); @@ -783,7 +783,7 @@ void P_PreTicker(INT32 frames) { P_MapStart(); - LUAh_PreThinkFrame(); + LUA_HOOK(PreThinkFrame); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) @@ -810,7 +810,7 @@ void P_PreTicker(INT32 frames) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - LUAh_ThinkFrame(); + LUA_HookThinkFrame(); // Run shield positioning P_RunShields(); @@ -819,7 +819,7 @@ void P_PreTicker(INT32 frames) P_UpdateSpecials(); P_RespawnSpecials(); - LUAh_PostThinkFrame(); + LUA_HOOK(PostThinkFrame); P_MapEnd(); } diff --git a/src/p_tick.h b/src/p_tick.h index 1fb88f3f2..ae481c6a2 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_user.c b/src/p_user.c index 02592053d..c3184b52f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1111,7 +1111,7 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) return false; { - UINT8 shouldCollide = LUAh_PlayerCanDamage(player, thing); + UINT8 shouldCollide = LUA_HookPlayerCanDamage(player, thing); if (P_MobjWasRemoved(thing)) return false; // removed??? if (shouldCollide == 1) @@ -1594,7 +1594,7 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname) break; case JT_OTHER: // Other state - result = LUAh_ShouldJingleContinue(&players[i], musname); + result = LUA_HookShouldJingleContinue(&players[i], musname); break; case JT_NONE: // Null state @@ -1860,7 +1860,7 @@ void P_SpawnShieldOrb(player_t *player) I_Error("P_SpawnShieldOrb: player->mo is NULL!\n"); #endif - if (LUAh_ShieldSpawn(player)) + if (LUA_HookPlayer(player, HOOK(ShieldSpawn))) return; if (player->powers[pw_shield] & SH_FORCE) @@ -2016,6 +2016,8 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) { mobj_t *ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST); + P_SetTarget(&ghost->target, mobj); + P_SetScale(ghost, mobj->scale); ghost->destscale = mobj->scale; @@ -4581,7 +4583,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_SPIN) { - if (LUAh_SpinSpecial(player)) + if (LUA_HookPlayer(player, HOOK(SpinSpecial))) return; } @@ -5053,7 +5055,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player))) // Spin button effects + if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5177,7 +5179,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // and you don't have a shield, do it! P_DoSuperTransformation(player, false); } - else if (!LUAh_JumpSpinSpecial(player)) + else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) switch (player->charability) { case CA_THOK: @@ -5250,7 +5252,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_JUMP && !player->exiting && !P_PlayerInPain(player)) { - if (LUAh_JumpSpecial(player)) + if (LUA_HookPlayer(player, HOOK(JumpSpecial))) ; // all situations below this require jump button not to be pressed already else if (player->pflags & PF_JUMPDOWN) @@ -5285,7 +5287,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) }*/ else if (player->pflags & PF_JUMPED) { - if (!LUAh_AbilitySpecial(player)) + if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) switch (player->charability) { case CA_THOK: @@ -5299,7 +5301,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) fixed_t actionspd = player->actionspd; if (player->charflags & SF_DASHMODE) - actionspd = max(player->normalspeed, FixedDiv(player->speed, player->mo->scale)); + actionspd = max(player->actionspd, FixedDiv(player->speed, player->mo->scale)); if (player->mo->eflags & MFE_UNDERWATER) actionspd >>= 1; @@ -5478,7 +5480,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } else if (player->pflags & PF_THOKKED) { - if (!LUAh_AbilitySpecial(player)) + if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) switch (player->charability) { case CA_FLY: @@ -5501,7 +5503,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; } } - else if ((!(player->charflags & SF_NOSHIELDABILITY)) && ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super] && !LUAh_ShieldSpecial(player))) + else if ((!(player->charflags & SF_NOSHIELDABILITY)) && ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super] && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) P_DoJumpShield(player); } @@ -8651,14 +8653,16 @@ void P_MovePlayer(player_t *player) { boolean atspinheight = false; fixed_t oldheight = player->mo->height; + fixed_t luaheight = LUA_HookPlayerHeight(player); + if (luaheight != -1) + { + player->mo->height = luaheight; + if (luaheight <= P_GetPlayerSpinHeight(player)) + atspinheight = true; // spinning will not save you from being crushed + } // Less height while spinning. Good for spinning under things...? - if ((player->mo->state == &states[player->mo->info->painstate]) - || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) - || (player->pflags & PF_SPINNING) - || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING - || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) - || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) + else if (P_PlayerShouldUseSpinHeight(player)) { player->mo->height = P_GetPlayerSpinHeight(player); atspinheight = true; @@ -9015,8 +9019,11 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE))) mo->flags = (mo->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; - if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! + if (mo->type == MT_EGGGUARD && mo->tracer) // Egg Guard's shield needs to be removed if it has one! + { P_KillMobj(mo->tracer, inflictor, source, DMG_NUKE); + P_KillMobj(mo, inflictor, source, DMG_NUKE); + } if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players! P_DamageMobj(mo, inflictor, source, 1, DMG_NUKE); @@ -10508,7 +10515,7 @@ boolean P_SpectatorJoinGame(player_t *player) else changeto = (P_RandomFixed() & 1) + 1; - if (!LUAh_TeamSwitch(player, changeto, true, false, false)) + if (!LUA_HookTeamSwitch(player, changeto, true, false, false)) return false; if (player->mo) @@ -10525,7 +10532,7 @@ boolean P_SpectatorJoinGame(player_t *player) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -10543,7 +10550,7 @@ boolean P_SpectatorJoinGame(player_t *player) // respawn in place and sit there for the rest of the round. if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE))) { - if (!LUAh_TeamSwitch(player, 3, true, false, false)) + if (!LUA_HookTeamSwitch(player, 3, true, false, false)) return false; if (player->mo) { @@ -10570,7 +10577,7 @@ boolean P_SpectatorJoinGame(player_t *player) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -11361,8 +11368,9 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) mobj_t *mo = player->mo; angle_t angle = player->drawangle; fixed_t dist; + fixed_t heightoffset = ((mo->eflags & MFE_VERTICALFLIP) ? mo->height - (P_GetPlayerHeight(player) >> 1) : (P_GetPlayerHeight(player) >> 1)); panim_t panim = player->panim; - tic_t dashmode = player->dashmode; + tic_t dashmode = min(player->dashmode, DASHMODE_MAX); boolean underwater = mo->eflags & MFE_UNDERWATER; statenum_t stat = fume->state-states; @@ -11394,7 +11402,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) offsetV = i*P_ReturnThrustY(fume, fume->movedir, radiusV); x = mo->x + radiusX + FixedMul(offsetH, factorX); y = mo->y + radiusY + FixedMul(offsetH, factorY); - z = mo->z + (mo->height >> 1) + offsetV; + z = mo->z + heightoffset + offsetV; P_SpawnMobj(x, y, z, MT_SMALLBUBBLE)->scale = mo->scale >> 1; } @@ -11457,7 +11465,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) P_UnsetThingPosition(fume); fume->x = mo->x + P_ReturnThrustX(fume, angle, dist); fume->y = mo->y + P_ReturnThrustY(fume, angle, dist); - fume->z = mo->z + ((mo->height - fume->height) >> 1); + fume->z = mo->z + heightoffset - (fume->height >> 1); P_SetThingPosition(fume); // If dashmode is high enough, spawn a trail @@ -11495,7 +11503,7 @@ void P_PlayerThink(player_t *player) } if (player->playerstate == PST_REBORN) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -11597,7 +11605,7 @@ void P_PlayerThink(player_t *player) if (player->playerstate == PST_DEAD) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -11718,7 +11726,7 @@ void P_PlayerThink(player_t *player) { player->mo->flags2 &= ~MF2_SHADOW; P_DeathThink(player); - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } @@ -11760,7 +11768,7 @@ void P_PlayerThink(player_t *player) { if (P_SpectatorJoinGame(player)) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; // player->mo was removed. } } @@ -11865,7 +11873,7 @@ void P_PlayerThink(player_t *player) if (!player->mo) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; // P_MovePlayer removed player->mo. } @@ -12319,7 +12327,7 @@ void P_PlayerThink(player_t *player) } #undef dashmode - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); /* // Colormap verification @@ -12614,14 +12622,14 @@ void P_PlayerAfterThink(player_t *player) if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > player->mo->radius) player->powers[pw_carry] = CR_NONE; - if (player->powers[pw_carry] != CR_NONE) + if (player->powers[pw_carry] == CR_PLAYER) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) tails->player->powers[pw_tailsfly] = 0; } - else + else if (player->powers[pw_carry] == CR_NONE) P_SetTarget(&player->mo->tracer, NULL); if (player-players == consoleplayer && botingame) @@ -12724,9 +12732,15 @@ void P_PlayerAfterThink(player_t *player) if (player->cmd.forwardmove || player->cmd.sidemove) { - rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); + rock->flags2 |= MF2_STRONGBOX; // signifies the rock should not slow to a halt + if (twodlevel || (mo->flags2 & MF2_TWOD)) + rock->movedir = mo->angle; + else + rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); P_Thrust(rock, rock->movedir, rock->scale >> 1); } + else + rock->flags2 &= ~MF2_STRONGBOX; mo->momx = rock->momx; mo->momy = rock->momy; @@ -12742,7 +12756,7 @@ void P_PlayerAfterThink(player_t *player) mo->tics = walktics; } - P_TeleportMove(player->mo, rock->x, rock->y, rock->z + rock->height); + P_TeleportMove(player->mo, rock->x, rock->y, rock->z + ((mo->eflags & MFE_VERTICALFLIP) ? -mo->height : rock->height)); break; } case CR_PTERABYTE: // being carried by a Pterabyte @@ -12882,7 +12896,7 @@ void P_PlayerAfterThink(player_t *player) if (player->followmobj) { - if (LUAh_FollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) + if (LUA_HookFollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) {;} else { @@ -12953,3 +12967,37 @@ boolean P_PlayerFullbright(player_t *player) || !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] && player->mo->state < &states[S_PLAY_NIGHTS_TRANS6])))); // Note the < instead of <= } + +#define JUMPCURLED(player) ((player->pflags & PF_JUMPED)\ + && (!(player->charflags & SF_NOJUMPSPIN))\ + && (player->panim == PA_JUMP || player->panim == PA_ROLL))\ + +// returns true if the player can enter a sector that they could not if standing at their skin's full height +boolean P_PlayerCanEnterSpinGaps(player_t *player) +{ + UINT8 canEnter = LUA_HookPlayerCanEnterSpinGaps(player); + if (canEnter == 1) + return true; + else if (canEnter == 2) + return false; + + return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) // players who are spinning, sliding, or gliding + || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) // players who are landing from a glide + || ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) + && player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH) // machine players in dashmode + || JUMPCURLED(player)); // players who are jumpcurled, but only if they would normally jump that way +} + +// returns true if the player should use their skin's spinheight instead of their skin's height +boolean P_PlayerShouldUseSpinHeight(player_t *player) +{ + return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) + || (player->mo->state == &states[player->mo->info->painstate]) + || (player->panim == PA_ROLL) + || ((player->powers[pw_tailsfly] || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) + && !(player->charflags & SF_NOJUMPSPIN)) + || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) + || ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) + && player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH) + || JUMPCURLED(player)); +} diff --git a/src/r_bsp.c b/src/r_bsp.c index 6f2a90d2d..5acd4e70c 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_bsp.h b/src/r_bsp.h index e2da8ebaf..40d24ffec 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_data.c b/src/r_data.c index af672f6dc..2cfe9cb7a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -30,10 +30,6 @@ #include "byteptr.h" #include "dehacked.h" -#ifdef _WIN32 -#include // alloca(sizeof) -#endif - // // Graphics. // SRB2 graphics for walls and sprites diff --git a/src/r_data.h b/src/r_data.h index aec52b54b..571fdc54f 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_defs.h b/src/r_defs.h index 9c649fbc4..1be3a1b8c 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw.c b/src/r_draw.c index c3d4efae3..f0a19a462 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,6 +25,7 @@ #include "w_wad.h" #include "z_zone.h" #include "console.h" // Until buffering gets finished +#include "libdivide.h" // used by NPO2 tilted span functions #ifdef HWRENDER #include "hardware/hw_main.h" @@ -173,14 +174,12 @@ static INT32 CacheIndexToSkin(INT32 ttc) CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; -#define TRANSTAB_AMTMUL10 (256.0f / 10.0f) - /** \brief Initializes the translucency tables used by the Software renderer. */ void R_InitTranslucencyTables(void) { - // Load here the transparency lookup tables 'TINTTAB' - // NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm + // Load here the transparency lookup tables 'TRANSx0' + // NOTE: the TRANSx0 resources MUST BE aligned on 64k for the asm // optimised code (in other words, transtables pointer low word is 0) transtables = Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC, NULL, 16); @@ -198,42 +197,14 @@ void R_InitTranslucencyTables(void) R_GenerateBlendTables(); } -void R_GenerateBlendTables(void) -{ - INT32 i; - - for (i = 0; i < NUMBLENDMAPS; i++) - { - if (i == blendtab_modulate) - continue; - blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16); - } - - for (i = 0; i <= 9; i++) - { - const size_t offs = (0x10000 * i); - const UINT8 alpha = TRANSTAB_AMTMUL10 * i; - - R_GenerateTranslucencyTable(blendtables[blendtab_add] + offs, AST_ADD, alpha); - R_GenerateTranslucencyTable(blendtables[blendtab_subtract] + offs, AST_SUBTRACT, alpha); - R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha); - } - - // Modulation blending only requires a single table - blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16); - R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0); -} - static colorlookup_t transtab_lut; -void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt) +static void BlendTab_Translucent(UINT8 *table, int style, UINT8 blendamt) { INT16 bg, fg; if (table == NULL) - I_Error("R_GenerateTranslucencyTable: input table was NULL!"); - - InitColorLUT(&transtab_lut, pMasterPalette, false); + I_Error("BlendTab_Translucent: input table was NULL!"); for (bg = 0; bg < 0xFF; bg++) { @@ -243,12 +214,123 @@ void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt) RGBA_t frontrgba = V_GetMasterColor(fg); RGBA_t result; - result.rgba = ASTBlendPixel(backrgba, frontrgba, style, blendamt); + result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF); + result.rgba = ASTBlendPixel(result, frontrgba, AST_TRANSLUCENT, blendamt); + table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); } } } +static void BlendTab_Subtractive(UINT8 *table, int style, UINT8 blendamt) +{ + INT16 bg, fg; + + if (table == NULL) + I_Error("BlendTab_Subtractive: input table was NULL!"); + + if (blendamt == 0xFF) + { + memset(table, GetColorLUT(&transtab_lut, 0, 0, 0), 0x10000); + return; + } + + for (bg = 0; bg < 0xFF; bg++) + { + for (fg = 0; fg < 0xFF; fg++) + { + RGBA_t backrgba = V_GetMasterColor(bg); + RGBA_t frontrgba = V_GetMasterColor(fg); + RGBA_t result; + + result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF); + result.s.red = max(0, result.s.red - blendamt); + result.s.green = max(0, result.s.green - blendamt); + result.s.blue = max(0, result.s.blue - blendamt); + + table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); + } + } +} + +static void BlendTab_Modulative(UINT8 *table) +{ + INT16 bg, fg; + + if (table == NULL) + I_Error("BlendTab_Modulative: input table was NULL!"); + + for (bg = 0; bg < 0xFF; bg++) + { + for (fg = 0; fg < 0xFF; fg++) + { + RGBA_t backrgba = V_GetMasterColor(bg); + RGBA_t frontrgba = V_GetMasterColor(fg); + RGBA_t result; + result.rgba = ASTBlendPixel(backrgba, frontrgba, AST_MODULATE, 0); + table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); + } + } +} + +static INT32 BlendTab_Count[NUMBLENDMAPS] = +{ + NUMTRANSTABLES+1, // blendtab_add + NUMTRANSTABLES+1, // blendtab_subtract + NUMTRANSTABLES+1, // blendtab_reversesubtract + 1 // blendtab_modulate +}; + +static INT32 BlendTab_FromStyle[] = +{ + 0, // AST_COPY + 0, // AST_TRANSLUCENT + blendtab_add, // AST_ADD + blendtab_subtract, // AST_SUBTRACT + blendtab_reversesubtract, // AST_REVERSESUBTRACT + blendtab_modulate, // AST_MODULATE + 0 // AST_OVERLAY +}; + +static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8 *, int, UINT8)) +{ + INT32 i = 0, num = BlendTab_Count[tab]; + const float amtmul = (256.0f / (float)(NUMTRANSTABLES + 1)); + for (; i < num; i++) + { + const size_t offs = (0x10000 * i); + const UINT16 alpha = min(amtmul * i, 0xFF); + genfunc(blendtables[tab] + offs, style, alpha); + } +} + +void R_GenerateBlendTables(void) +{ + INT32 i; + + for (i = 0; i < NUMBLENDMAPS; i++) + blendtables[i] = Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16); + + InitColorLUT(&transtab_lut, pMasterPalette, false); + + // Additive + BlendTab_GenerateMaps(blendtab_add, AST_ADD, BlendTab_Translucent); + + // Subtractive +#if 1 + BlendTab_GenerateMaps(blendtab_subtract, AST_SUBTRACT, BlendTab_Subtractive); +#else + BlendTab_GenerateMaps(blendtab_subtract, AST_SUBTRACT, BlendTab_Translucent); +#endif + + // Reverse subtractive + BlendTab_GenerateMaps(blendtab_reversesubtract, AST_REVERSESUBTRACT, BlendTab_Translucent); + + // Modulative blending only requires a single table + BlendTab_Modulative(blendtables[blendtab_modulate]); +} + +#define ClipBlendLevel(style, trans) max(min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0) #define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0) UINT8 *R_GetTranslucencyTable(INT32 alphalevel) @@ -258,7 +340,12 @@ UINT8 *R_GetTranslucencyTable(INT32 alphalevel) UINT8 *R_GetBlendTable(int style, INT32 alphalevel) { - size_t offs = (ClipTransLevel(alphalevel) << FF_TRANSSHIFT); + size_t offs; + + if (style <= AST_COPY || style >= AST_OVERLAY) + return NULL; + + offs = (ClipBlendLevel(style, alphalevel) << FF_TRANSSHIFT); // Lactozilla: Returns the equivalent to AST_TRANSLUCENT // if no alpha style matches any of the blend tables. @@ -283,6 +370,14 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel) return NULL; } +boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel) +{ + if (blendmode <= AST_COPY || blendmode == AST_SUBTRACT || blendmode == AST_MODULATE || blendmode >= AST_OVERLAY) + return true; + + return (alphalevel < BlendTab_Count[BlendTab_FromStyle[blendmode]]); +} + // Define for getting accurate color brightness readings according to how the human eye sees them. // https://en.wikipedia.org/wiki/Relative_luminance // 0.2126 to red @@ -387,8 +482,12 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U // White! if (skinnum == TC_BOSS) { + UINT8 *originalColormap = R_GetTranslationColormap(TC_DEFAULT, (skincolornum_t)color, GTC_CACHE); for (i = 0; i < 16; i++) + { + dest_colormap[DEFAULT_STARTTRANSCOLOR + i] = originalColormap[DEFAULT_STARTTRANSCOLOR + i]; dest_colormap[31-i] = i; + } } else if (skinnum == TC_METALSONIC) { diff --git a/src/r_draw.h b/src/r_draw.h index d1eb83033..2173c7a5a 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -140,11 +140,12 @@ extern UINT8 *blendtables[NUMBLENDMAPS]; void R_InitTranslucencyTables(void); void R_GenerateBlendTables(void); -void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt); UINT8 *R_GetTranslucencyTable(INT32 alphalevel); UINT8 *R_GetBlendTable(int style, INT32 alphalevel); +boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); + // Color ramp modification should force a recache extern UINT8 skincolor_modified[]; @@ -176,7 +177,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); -#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) +#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan)) void R_DrawSpan_8(void); void R_DrawTranslucentSpan_8(void); diff --git a/src/r_draw16.c b/src/r_draw16.c index 8b1d29e8d..1a2fed773 100644 --- a/src/r_draw16.c +++ b/src/r_draw16.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw8.c b/src/r_draw8.c index e78ba8a6c..b8a63d5c0 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -693,8 +693,8 @@ void R_DrawTiltedSpan_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); @@ -726,8 +726,8 @@ void R_DrawTiltedSpan_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -763,8 +763,8 @@ void R_DrawTiltedSpan_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -826,8 +826,8 @@ void R_DrawTiltedTranslucentSpan_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); @@ -858,8 +858,8 @@ void R_DrawTiltedTranslucentSpan_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -895,8 +895,8 @@ void R_DrawTiltedTranslucentSpan_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -960,8 +960,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); @@ -992,8 +992,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1029,8 +1029,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -1091,8 +1091,8 @@ void R_DrawTiltedSplat_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); @@ -1127,8 +1127,8 @@ void R_DrawTiltedSplat_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1168,8 +1168,8 @@ void R_DrawTiltedSplat_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -1227,8 +1227,9 @@ void R_DrawSplat_8 (void) // need! // // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) + // Why decimal? 0x3FFFFF == 4194303... ~Golden val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[0] = colormap[val]; @@ -1236,7 +1237,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[1] = colormap[val]; @@ -1244,7 +1245,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[2] = colormap[val]; @@ -1252,7 +1253,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[3] = colormap[val]; @@ -1260,7 +1261,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[4] = colormap[val]; @@ -1268,7 +1269,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[5] = colormap[val]; @@ -1276,7 +1277,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[6] = colormap[val]; @@ -1284,7 +1285,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[7] = colormap[val]; @@ -1447,10 +1448,7 @@ void R_DrawFloorSprite_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[0] = colormap[translation[val & 0xFF]]; @@ -1458,7 +1456,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[1] = colormap[translation[val & 0xFF]]; @@ -1466,7 +1463,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[2] = colormap[translation[val & 0xFF]]; @@ -1474,7 +1470,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[3] = colormap[translation[val & 0xFF]]; @@ -1482,7 +1477,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[4] = colormap[translation[val & 0xFF]]; @@ -1490,7 +1484,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[5] = colormap[translation[val & 0xFF]]; @@ -1498,7 +1491,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[6] = colormap[translation[val & 0xFF]]; @@ -1506,7 +1498,6 @@ void R_DrawFloorSprite_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; val = source[val]; if (val & 0xFF00) dest[7] = colormap[translation[val & 0xFF]]; @@ -1682,8 +1673,8 @@ void R_DrawTiltedFloorSprite_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1722,8 +1713,8 @@ void R_DrawTiltedFloorSprite_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -1791,8 +1782,8 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1831,8 +1822,8 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index a34a20e9a..71ec99948 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -106,6 +106,9 @@ void R_DrawTiltedSpan_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -133,24 +136,25 @@ void R_DrawTiltedSpan_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -181,25 +185,26 @@ void R_DrawTiltedSpan_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -220,17 +225,18 @@ void R_DrawTiltedSpan_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -248,25 +254,26 @@ void R_DrawTiltedSpan_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -299,6 +306,9 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -326,23 +336,24 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -373,25 +384,26 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -412,17 +424,18 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -440,25 +453,26 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -490,6 +504,9 @@ void R_DrawTiltedSplat_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -517,24 +534,25 @@ void R_DrawTiltedSplat_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -569,25 +587,26 @@ void R_DrawTiltedSplat_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -610,17 +629,18 @@ void R_DrawTiltedSplat_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -640,8 +660,8 @@ void R_DrawTiltedSplat_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -649,17 +669,18 @@ void R_DrawTiltedSplat_NPO2_8(void) val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -1002,14 +1023,14 @@ void R_DrawTiltedFloorSprite_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1040,8 +1061,8 @@ void R_DrawTiltedFloorSprite_NPO2_8(void) v = (INT64)(startv); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1070,14 +1091,14 @@ void R_DrawTiltedFloorSprite_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1152,14 +1173,14 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1190,8 +1211,8 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) v = (INT64)(startv); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1220,14 +1241,14 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1401,6 +1422,9 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -1429,23 +1453,24 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } @@ -1476,25 +1501,26 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } @@ -1515,17 +1541,18 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } @@ -1543,25 +1570,26 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } diff --git a/src/r_local.h b/src/r_local.h index 4ccb766cf..ba78ea87d 100644 --- a/src/r_local.h +++ b/src/r_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_main.c b/src/r_main.c index f82fb589e..17e124cb9 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -955,7 +955,7 @@ void R_ExecuteSetViewSize(void) j = viewheight*16; for (i = 0; i < j; i++) { - dy = ((i - viewheight*8)<>FRACBITS) * viewwidth/BASEVIDWIDTH; - yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)]; - } + centeryfrac = (viewheight/2)<topdelta != 0xff) { + UINT8 *s8 = NULL; + UINT16 *s16 = NULL; + UINT32 *s32 = NULL; + topdelta = column->topdelta; if (topdelta <= prevdelta) topdelta += prevdelta; prevdelta = topdelta; - s8 = (UINT8 *)(column) + 3; - if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) - s32 = (UINT32 *)s8; - else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) - s16 = (UINT16 *)s8; - for (ofs = 0; ofs < column->length; ofs++) + + ofs = (y - topdelta); + + if (y >= topdelta && ofs < column->length) { - if ((topdelta + ofs) == y) + s8 = (UINT8 *)(column) + 3; + switch (inbpp) { - if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) + case PICDEPTH_32BPP: + s32 = (UINT32 *)s8; return &s32[ofs]; - else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) + case PICDEPTH_16BPP: + s16 = (UINT16 *)s8; return &s16[ofs]; - else // PICDEPTH_8BPP + default: // PICDEPTH_8BPP return &s8[ofs]; } } - if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) + + if (inbpp == PICDEPTH_32BPP) column = (column_t *)((UINT32 *)column + column->length); - else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) + else if (inbpp == PICDEPTH_16BPP) column = (column_t *)((UINT16 *)column + column->length); else column = (column_t *)((UINT8 *)column + column->length); @@ -979,8 +983,8 @@ static png_bytep *PNG_Read( for (i = 0; i < 256; i++) { - UINT32 rgb = R_PutRgbaRGBA(pal->red, pal->green, pal->blue, 0xFF); - if (rgb != pMasterPalette[i].rgba) + byteColor_t *curpal = &(pMasterPalette[i].s); + if (pal->red != curpal->red || pal->green != curpal->green || pal->blue != curpal->blue) { usepal = false; break; @@ -996,12 +1000,12 @@ static png_bytep *PNG_Read( { png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values); - if (trans && trans_num == 256) + if (trans && trans_num > 0) { INT32 i; for (i = 0; i < trans_num; i++) { - // libpng will transform this image into RGB even if + // libpng will transform this image into RGBA even if // the transparent index does not exist in the image, // and there is no way around that. if (trans[i] < 0xFF) diff --git a/src/r_picformats.h b/src/r_picformats.h index 8d3999013..b1bb35edd 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2020 by Sonic Team Junior. +// Copyright (C) 2018-2021 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_plane.c b/src/r_plane.c index 45d635213..4c757d8ca 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -31,13 +31,6 @@ #include "z_zone.h" #include "p_tick.h" -#ifdef TIMING -#include "p5prof.h" - INT64 mycount; - INT64 mytotal = 0; - UINT32 nombre = 100000; -#endif - // // opening // @@ -104,6 +97,7 @@ fixed_t cachedxstep[MAXVIDHEIGHT]; fixed_t cachedystep[MAXVIDHEIGHT]; static fixed_t xoffs, yoffs; +static floatv3_t ds_slope_origin, ds_slope_u, ds_slope_v; // // R_InitPlanes @@ -127,21 +121,20 @@ struct boolean active; } planeripple; -static void R_CalculatePlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight, boolean calcfrac) +// ripples da water texture +static fixed_t R_CalculateRippleOffset(INT32 y) { - fixed_t distance = FixedMul(plheight, yslope[y]); + fixed_t distance = FixedMul(planeheight, yslope[y]); const INT32 yay = (planeripple.offset + (distance>>9)) & 8191; + return FixedDiv(FINESINE(yay), (1<<12) + (distance>>11)); +} - // ripples da water texture - ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; - - if (calcfrac) - { - angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT; - angle = (angle + 2048) & 8191; // 90 degrees - planeripple.xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs<>= ANGLETOFINESHIFT; + angle = (angle + 2048) & 8191; // 90 degrees + planeripple.xfrac = FixedMul(FINECOSINE(angle), ds_bgofs); + planeripple.yfrac = FixedMul(FINESINE(angle), ds_bgofs); } static void R_UpdatePlaneRipple(void) @@ -154,16 +147,12 @@ static void R_UpdatePlaneRipple(void) // R_MapPlane // // Uses global vars: +// planeheight // basexscale // baseyscale // centerx -// viewx -// viewy -// viewsin -// viewcos -// viewheight -void R_MapPlane(INT32 y, INT32 x1, INT32 x2) +static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; fixed_t distance = 0, span; @@ -177,60 +166,50 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) if (x1 >= vid.width) x1 = vid.width - 1; - if (!currentplane->slope) + angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; + planecos = FINECOSINE(angle); + planesin = FINESINE(angle); + + if (planeheight != cachedheight[y]) { - angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; - planecos = FINECOSINE(angle); - planesin = FINESINE(angle); + cachedheight[y] = planeheight; + cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); + span = abs(centery - y); - if (planeheight != cachedheight[y]) + if (span) // don't divide by zero { - cachedheight[y] = planeheight; - cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); - span = abs(centery - y); - - if (span) // don't divide by zero - { - ds_xstep = FixedMul(planesin, planeheight) / span; - ds_ystep = FixedMul(planecos, planeheight) / span; - } - else - { - ds_xstep = FixedMul(distance, basexscale); - ds_ystep = FixedMul(distance, baseyscale); - } - - cachedxstep[y] = ds_xstep; - cachedystep[y] = ds_ystep; + ds_xstep = FixedMul(planesin, planeheight) / span; + ds_ystep = FixedMul(planecos, planeheight) / span; } else { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; + ds_xstep = FixedMul(distance, basexscale); + ds_ystep = FixedMul(distance, baseyscale); } - ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; - ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; + cachedxstep[y] = ds_xstep; + cachedystep[y] = ds_ystep; } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; + ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; // Water ripple effect if (planeripple.active) { - // Needed for ds_bgofs - R_CalculatePlaneRipple(currentplane, y, planeheight, (!currentplane->slope)); + ds_bgofs = R_CalculateRippleOffset(y); - if (currentplane->slope) - { - ds_sup = &ds_su[y]; - ds_svp = &ds_sv[y]; - ds_szp = &ds_sz[y]; - } - else - { - ds_xfrac += planeripple.xfrac; - ds_yfrac += planeripple.yfrac; - } + R_CalculatePlaneRipple(currentplane->viewangle + currentplane->plangle); + + ds_xfrac += planeripple.xfrac; + ds_yfrac += planeripple.yfrac; + ds_bgofs >>= FRACBITS; if ((y + ds_bgofs) >= viewheight) ds_bgofs = viewheight-y-1; @@ -238,16 +217,11 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_bgofs = -y; } - if (currentplane->slope) - ds_colormap = colormaps; - else - { - pindex = distance >> LIGHTZSHIFT; - if (pindex >= MAXLIGHTZ) - pindex = MAXLIGHTZ - 1; - ds_colormap = planezlight[pindex]; - } + pindex = distance >> LIGHTZSHIFT; + if (pindex >= MAXLIGHTZ) + pindex = MAXLIGHTZ - 1; + ds_colormap = planezlight[pindex]; if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -255,19 +229,46 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_x1 = x1; ds_x2 = x2; - // profile drawer -#ifdef TIMING - ProfZeroTimer(); + spanfunc(); +} + +static void R_MapTiltedPlane(INT32 y, INT32 x1, INT32 x2) +{ +#ifdef RANGECHECK + if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) + I_Error("R_MapTiltedPlane: %d, %d at %d", x1, x2, y); #endif + if (x1 >= vid.width) + x1 = vid.width - 1; + + // Water ripple effect + if (planeripple.active) + { + ds_bgofs = R_CalculateRippleOffset(y); + + ds_sup = &ds_su[y]; + ds_svp = &ds_sv[y]; + ds_szp = &ds_sz[y]; + + ds_bgofs >>= FRACBITS; + + if ((y + ds_bgofs) >= viewheight) + ds_bgofs = viewheight-y-1; + if ((y + ds_bgofs) < 0) + ds_bgofs = -y; + } + + if (currentplane->extra_colormap) + ds_colormap = currentplane->extra_colormap->colormap; + else + ds_colormap = colormaps; + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + spanfunc(); - -#ifdef TIMING - RDMSR(0x10, &mycount); - mytotal += mycount; // 64bit add - if (!(nombre--)) - I_Error("spanfunc() CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1), (INT32)mytotal); -#endif } void R_ClearFFloorClips (void) @@ -367,11 +368,11 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, if (plangle != 0) { // Add the view offset, rotated by the plane angle. - fixed_t cosinecomponent = FINECOSINE(plangle>>ANGLETOFINESHIFT); - fixed_t sinecomponent = FINESINE(plangle>>ANGLETOFINESHIFT); - fixed_t oldxoff = xoff; - xoff = FixedMul(xoff,cosinecomponent)+FixedMul(yoff,sinecomponent); - yoff = -FixedMul(oldxoff,sinecomponent)+FixedMul(yoff,cosinecomponent); + float ang = ANG2RAD(plangle); + float x = FixedToFloat(xoff); + float y = FixedToFloat(yoff); + xoff = FloatToFixed(x * cos(ang) + y * sin(ang)); + yoff = FloatToFixed(-x * sin(ang) + y * cos(ang)); } } @@ -575,12 +576,9 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) } -// -// R_MakeSpans -// -void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) +static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) { - // Alam: from r_splats's R_RenderFloorSplat + // Alam: from r_splats's R_RasterizeFloorSplat if (t1 >= vid.height) t1 = vid.height-1; if (b1 >= vid.height) b1 = vid.height-1; if (t2 >= vid.height) t2 = vid.height-1; @@ -604,10 +602,35 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) spanstart[b2--] = x; } +static void R_MakeTiltedSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) +{ + // Alam: from r_splats's R_RasterizeFloorSplat + if (t1 >= vid.height) t1 = vid.height-1; + if (b1 >= vid.height) b1 = vid.height-1; + if (t2 >= vid.height) t2 = vid.height-1; + if (b2 >= vid.height) b2 = vid.height-1; + if (x-1 >= vid.width) x = vid.width; + + while (t1 < t2 && t1 <= b1) + { + R_MapTiltedPlane(t1, spanstart[t1], x - 1); + t1++; + } + while (b1 > b2 && b1 >= t1) + { + R_MapTiltedPlane(b1, spanstart[b1], x - 1); + b1--; + } + + while (t2 < t1 && t2 <= b2) + spanstart[t2++] = x; + while (b2 > b1 && b2 >= t2) + spanstart[b2--] = x; +} + void R_DrawPlanes(void) { visplane_t *pl; - angle_t va = viewangle; INT32 i; R_UpdatePlaneRipple(); @@ -622,8 +645,6 @@ void R_DrawPlanes(void) R_DrawSinglePlane(pl); } } - - viewangle = va; } // R_DrawSkyPlane @@ -669,69 +690,109 @@ static void R_DrawSkyPlane(visplane_t *pl) } } -// Potentially override other stuff for now cus we're mean. :< But draw a slope plane! -// I copied ZDoom's code and adapted it to SRB2... -Red -void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge) +// Returns the height of the sloped plane at (x, y) as a 32.16 fixed_t +static INT64 R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) { - floatv3_t p, m, n; - float ang; - float vx, vy, vz; - float xscale = FIXED_TO_FLOAT(planexscale); - float yscale = FIXED_TO_FLOAT(planeyscale); - // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly - // use this as a temp var to store P_GetSlopeZAt's return value each time - fixed_t temp; + INT64 x64 = ((INT64)x - (INT64)slope->o.x); + INT64 y64 = ((INT64)y - (INT64)slope->o.y); - vx = FIXED_TO_FLOAT(planeviewx+planexoffset); - vy = FIXED_TO_FLOAT(planeviewy-planeyoffset); - vz = FIXED_TO_FLOAT(planeviewz); + x64 = (x64 * (INT64)slope->d.x) / FRACUNIT; + y64 = (y64 * (INT64)slope->d.y) / FRACUNIT; - temp = P_GetSlopeZAt(slope, planeviewx, planeviewy); - zeroheight = FIXED_TO_FLOAT(temp); + return (INT64)slope->o.z + ((x64 + y64) * (INT64)slope->zdelta) / FRACUNIT; +} + +// Sets the texture origin vector of the sloped plane. +static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) +{ + floatv3_t *p = &ds_slope_origin; + + INT64 vx = (INT64)xpos + (INT64)xoff; + INT64 vy = (INT64)ypos - (INT64)yoff; + + float vxf = vx / (float)FRACUNIT; + float vyf = vy / (float)FRACUNIT; + float ang = ANG2RAD(ANGLE_270 - angle); // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - ang = ANG2RAD(ANGLE_270 - planeviewangle); - p.x = vx * cos(ang) - vy * sin(ang); - p.z = vx * sin(ang) + vy * cos(ang); - temp = P_GetSlopeZAt(slope, -planexoffset, planeyoffset); - p.y = FIXED_TO_FLOAT(temp) - vz; + p->x = vxf * cos(ang) - vyf * sin(ang); + p->z = vxf * sin(ang) + vyf * cos(ang); + p->y = (R_GetSlopeZAt(slope, -xoff, yoff) - zpos) / (float)FRACUNIT; +} + +// This function calculates all of the vectors necessary for drawing a sloped plane. +void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +{ + // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! + // I copied ZDoom's code and adapted it to SRB2... -Red + floatv3_t *m = &ds_slope_v, *n = &ds_slope_u; + fixed_t height, temp; + float ang; + + R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); + height = P_GetSlopeZAt(slope, xpos, ypos); + zeroheight = FixedToFloat(height - zpos); // m is the v direction vector in view space - ang = ANG2RAD(ANGLE_180 - (planeviewangle + planeangle)); - m.x = yscale * cos(ang); - m.z = yscale * sin(ang); + ang = ANG2RAD(ANGLE_180 - (angle + plangle)); + m->x = cos(ang); + m->z = sin(ang); // n is the u direction vector in view space - n.x = xscale * sin(ang); - n.z = -xscale * cos(ang); + n->x = sin(ang); + n->z = -cos(ang); - ang = ANG2RAD(planeangle); - temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(yscale * sin(ang)), planeviewy + FLOAT_TO_FIXED(yscale * cos(ang))); - m.y = FIXED_TO_FLOAT(temp) - zeroheight; - temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(xscale * cos(ang)), planeviewy - FLOAT_TO_FIXED(xscale * sin(ang))); - n.y = FIXED_TO_FLOAT(temp) - zeroheight; + plangle >>= ANGLETOFINESHIFT; + temp = P_GetSlopeZAt(slope, xpos + FINESINE(plangle), ypos + FINECOSINE(plangle)); + m->y = FixedToFloat(temp - height); + temp = P_GetSlopeZAt(slope, xpos + FINECOSINE(plangle), ypos - FINESINE(plangle)); + n->y = FixedToFloat(temp - height); +} - if (ds_powersoftwo) - { - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; +// This function calculates all of the vectors necessary for drawing a sloped and scaled plane. +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +{ + floatv3_t *m = &ds_slope_v, *n = &ds_slope_u; + fixed_t height, temp; - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; - } + float xscale = FixedToFloat(xs); + float yscale = FixedToFloat(ys); + float ang; + + R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); + height = P_GetSlopeZAt(slope, xpos, ypos); + zeroheight = FixedToFloat(height - zpos); + + // m is the v direction vector in view space + ang = ANG2RAD(ANGLE_180 - (angle + plangle)); + m->x = yscale * cos(ang); + m->z = yscale * sin(ang); + + // n is the u direction vector in view space + n->x = xscale * sin(ang); + n->z = -xscale * cos(ang); + + ang = ANG2RAD(plangle); + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(yscale * sin(ang)), ypos + FloatToFixed(yscale * cos(ang))); + m->y = FixedToFloat(temp - height); + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(xscale * cos(ang)), ypos - FloatToFixed(xscale * sin(ang))); + n->y = FixedToFloat(temp - height); +} + +void R_CalculateSlopeVectors(void) +{ + float sfmult = 65536.f; // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ d->x = (v1.y * v2.z) - (v1.z * v2.y);\ d->y = (v1.z * v2.x) - (v1.x * v2.z);\ d->z = (v1.x * v2.y) - (v1.y * v2.x) - CROSS(ds_sup, p, m); - CROSS(ds_svp, p, n); - CROSS(ds_szp, m, n); + CROSS(ds_sup, ds_slope_origin, ds_slope_v); + CROSS(ds_svp, ds_slope_origin, ds_slope_u); + CROSS(ds_szp, ds_slope_v, ds_slope_u); #undef CROSS ds_sup->z *= focallengthf; @@ -739,27 +800,15 @@ d->z = (v1.x * v2.y) - (v1.y * v2.x) ds_szp->z *= focallengthf; // Premultiply the texture vectors with the scale factors -#define SFMULT 65536.f if (ds_powersoftwo) - { - ds_sup->x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<x *= SFMULT; - ds_sup->y *= SFMULT; - ds_sup->z *= SFMULT; - ds_svp->x *= SFMULT; - ds_svp->y *= SFMULT; - ds_svp->z *= SFMULT; - } -#undef SFMULT + sfmult *= (1 << nflatshiftup); + + ds_sup->x *= sfmult; + ds_sup->y *= sfmult; + ds_sup->z *= sfmult; + ds_svp->x *= sfmult; + ds_svp->y *= sfmult; + ds_svp->z *= sfmult; } void R_SetTiltedSpan(INT32 span) @@ -776,10 +825,40 @@ void R_SetTiltedSpan(INT32 span) ds_szp = &ds_sz[span]; } -static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) +static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff) { R_SetTiltedSpan(y); - R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); + R_SetSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle); + R_CalculateSlopeVectors(); +} + +static inline void R_AdjustSlopeCoordinates(vector3_t *origin) +{ + const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + + fixed_t ox = (origin->x & modmask); + fixed_t oy = -(origin->y & modmask); + + xoffs &= modmask; + yoffs &= modmask; + + xoffs -= (origin->x - ox); + yoffs += (origin->y + oy); +} + +static inline void R_AdjustSlopeCoordinatesNPO2(vector3_t *origin) +{ + const fixed_t modmaskw = (ds_flatwidth << FRACBITS); + const fixed_t modmaskh = (ds_flatheight << FRACBITS); + + fixed_t ox = (origin->x % modmaskw); + fixed_t oy = -(origin->y % modmaskh); + + xoffs %= modmaskw; + yoffs %= modmaskh; + + xoffs -= (origin->x - ox); + yoffs += (origin->y + oy); } void R_DrawSinglePlane(visplane_t *pl) @@ -789,8 +868,8 @@ void R_DrawSinglePlane(visplane_t *pl) INT32 x; INT32 stop, angle; ffloor_t *rover; - int type; - int spanfunctype = BASEDRAWFUNC; + INT32 type; + INT32 spanfunctype = BASEDRAWFUNC; if (!(pl->minx <= pl->maxx)) return; @@ -950,7 +1029,6 @@ void R_DrawSinglePlane(visplane_t *pl) xoffs = pl->xoffs; yoffs = pl->yoffs; - planeheight = abs(pl->height - pl->viewz); if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; @@ -960,76 +1038,29 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - float fudgecanyon = 0; - angle_t hack = (pl->plangle & (ANGLE_90-1)); - - yoffs *= 1; - - if (ds_powersoftwo) + if (!pl->plangle) { - fixed_t temp; - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red - fudgecanyon = ((1<>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - - const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); - - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - - temp = ox & modmask; - oy &= modmask; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); - } + if (ds_powersoftwo) + R_AdjustSlopeCoordinates(&pl->slope->o); else - { - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - } - - xoffs = (fixed_t)(xoffs*fudgecanyon); - yoffs = (fixed_t)(yoffs/fudgecanyon); + R_AdjustSlopeCoordinatesNPO2(&pl->slope->o); } if (planeripple.active) { - fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); + planeheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); R_PlaneBounds(pl); for (x = pl->high; x < pl->low; x++) { - R_CalculatePlaneRipple(pl, x, plheight, true); - R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac), fudgecanyon); + ds_bgofs = R_CalculateRippleOffset(x); + R_CalculatePlaneRipple(pl->viewangle + pl->plangle); + R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac)); } } else - R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon); + R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs); switch (spanfunctype) { @@ -1050,7 +1081,10 @@ void R_DrawSinglePlane(visplane_t *pl) planezlight = scalelight[light]; } else + { + planeheight = abs(pl->height - pl->viewz); planezlight = zlight[light]; + } // Use the correct span drawer depending on the powers-of-twoness if (!ds_powersoftwo) @@ -1071,18 +1105,15 @@ void R_DrawSinglePlane(visplane_t *pl) stop = pl->maxx + 1; - if (viewx != pl->viewx || viewy != pl->viewy) + if (pl->slope) { - viewx = pl->viewx; - viewy = pl->viewy; + for (x = pl->minx; x <= stop; x++) + R_MakeTiltedSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); } - if (viewz != pl->viewz) - viewz = pl->viewz; - - for (x = pl->minx; x <= stop; x++) + else { - R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], - pl->top[x], pl->bottom[x]); + for (x = pl->minx; x <= stop; x++) + R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); } /* diff --git a/src/r_plane.h b/src/r_plane.h index 0d11c5b72..bdad77930 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -78,8 +78,6 @@ void R_InitPlanes(void); void R_ClearPlanes(void); void R_ClearFFloorClips (void); -void R_MapPlane(INT32 y, INT32 x1, INT32 x2); -void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2); void R_DrawPlanes(void); visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope); @@ -94,7 +92,9 @@ boolean R_CheckPowersOfTwo(void); void R_DrawSinglePlane(visplane_t *pl); // Calculates the slope vectors needed for tilted span drawing. -void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge); +void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); +void R_CalculateSlopeVectors(void); // Sets the slope vector pointers for the current tilted span. void R_SetTiltedSpan(INT32 span); diff --git a/src/r_portal.c b/src/r_portal.c index 1aca145ec..3026f4e4c 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_portal.h b/src/r_portal.h index e665a26e6..0effd07b5 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_segs.c b/src/r_segs.c index a6772f964..a8c85ec33 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1477,10 +1477,18 @@ static void R_RenderSegLoop (void) } for (i = 0; i < numffloors; i++) + { + if (curline->polyseg && (ffloor[i].polyobj != curline->polyseg)) + continue; + ffloor[i].f_frac += ffloor[i].f_step; + } for (i = 0; i < numbackffloors; i++) { + if (curline->polyseg && (ffloor[i].polyobj != curline->polyseg)) + continue; + ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF); ffloor[i].b_frac += ffloor[i].b_step; } diff --git a/src/r_segs.h b/src/r_segs.h index ace5711d4..da7d44ad4 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_skins.c b/src/r_skins.c index 6f150f234..b7eb24345 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -148,8 +148,6 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->contspeed = 17; skin->contangle = 0; - skin->availability = 0; - for (i = 0; i < sfx_skinsoundslot0; i++) if (S_sfx[i].skinsound != -1) skin->soundsid[S_sfx[i].skinsound] = i; @@ -176,14 +174,34 @@ void R_InitSkins(void) UINT32 R_GetSkinAvailabilities(void) { - INT32 s; UINT32 response = 0; + UINT32 unlockShift = 0; + INT32 i; - for (s = 0; s < MAXSKINS; s++) + for (i = 0; i < MAXUNLOCKABLES; i++) { - if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) - response |= (1 << s); + if (unlockables[i].type != SECRET_SKIN) + { + continue; + } + + if (unlockShift >= 32) + { + // This crash is impossible to trigger as is, + // but it could happen if MAXUNLOCKABLES is ever made higher than 32, + // and someone makes a mod that has 33+ unlockable characters. :V + I_Error("Too many unlockable characters\n"); + return 0; + } + + if (unlockables[i].unlocked) + { + response |= (1 << unlockShift); + } + + unlockShift++; } + return response; } @@ -191,14 +209,78 @@ UINT32 R_GetSkinAvailabilities(void) // warning don't use with an invalid skinnum other than -1 which always returns true boolean R_SkinUsable(INT32 playernum, INT32 skinnum) { - return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... - || (!skins[skinnum].availability) - || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) - || (modeattacking) // If you have someone else's run you might as well take a look - || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. - || (netgame && (cv_forceskin.value == skinnum)) // Force 2. - || (metalrecording && skinnum == 5) // Force 3. - ); + INT32 unlockID = -1; + UINT32 unlockShift = 0; + INT32 i; + + if (skinnum == -1) + { + // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... + return true; + } + + if (modeattacking) + { + // If you have someone else's run you might as well take a look + return true; + } + + if (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) + { + // Force 1. + return true; + } + + if (netgame && (cv_forceskin.value == skinnum)) + { + // Force 2. + return true; + } + + if (metalrecording && skinnum == 5) + { + // Force 3. + return true; + } + + // We will now check if this skin is supposed to be locked or not. + + for (i = 0; i < MAXUNLOCKABLES; i++) + { + INT32 unlockSkin = -1; + + if (unlockables[i].type != SECRET_SKIN) + { + continue; + } + + unlockSkin = M_UnlockableSkinNum(&unlockables[i]); + + if (unlockSkin == skinnum) + { + unlockID = i; + break; + } + + unlockShift++; + } + + if (unlockID == -1) + { + // This skin isn't locked at all, we're good. + return true; + } + + if ((netgame || multiplayer) && playernum != -1) + { + // We want to check per-player unlockables. + return (players[playernum].availabilities & (1 << unlockShift)); + } + else + { + // We want to check our global unlockables. + return (unlockables[unlockID].unlocked); + } } // returns true if the skin name is found (loaded from pwad) @@ -216,6 +298,103 @@ INT32 R_SkinAvailable(const char *name) return -1; } +// Auxillary function that actually sets the skin +static void SetSkin(player_t *player, INT32 skinnum) +{ + skin_t *skin = &skins[skinnum]; + UINT16 newcolor = 0; + + player->skin = skinnum; + + player->camerascale = skin->camerascale; + player->shieldscale = skin->shieldscale; + + player->charability = (UINT8)skin->ability; + player->charability2 = (UINT8)skin->ability2; + + player->charflags = (UINT32)skin->flags; + + player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; + player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; + player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; + player->followitem = skin->followitem; + + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff. + player->powers[pw_shield] &= SH_STACK; + + player->actionspd = skin->actionspd; + player->mindash = skin->mindash; + player->maxdash = skin->maxdash; + + player->normalspeed = skin->normalspeed; + player->runspeed = skin->runspeed; + player->thrustfactor = skin->thrustfactor; + player->accelstart = skin->accelstart; + player->acceleration = skin->acceleration; + + player->jumpfactor = skin->jumpfactor; + + player->height = skin->height; + player->spinheight = skin->spinheight; + + if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) + { + if (player == &players[consoleplayer]) + CV_StealthSetValue(&cv_playercolor, skin->prefcolor); + else if (player == &players[secondarydisplayplayer]) + CV_StealthSetValue(&cv_playercolor2, skin->prefcolor); + player->skincolor = newcolor = skin->prefcolor; + if (player->bot && botingame) + { + botskin = (UINT8)(skinnum + 1); + botcolor = skin->prefcolor; + } + } + + if (player->followmobj) + { + P_RemoveMobj(player->followmobj); + P_SetTarget(&player->followmobj, NULL); + } + + if (player->mo) + { + fixed_t radius = FixedMul(skin->radius, player->mo->scale); + if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. + { + skin = &skins[DEFAULTNIGHTSSKIN]; + player->followitem = skin->followitem; + if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) + newcolor = skin->prefcolor; // will be updated in thinker to flashing + } + player->mo->skin = skin; + if (newcolor) + player->mo->color = newcolor; + P_SetScale(player->mo, player->mo->scale); + player->mo->radius = radius; + + P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames + } +} + +// Gets the player to the first usuable skin in the game. +// (If your mod locked them all, then you kinda stupid) +INT32 GetPlayerDefaultSkin(INT32 playernum) +{ + INT32 i; + + for (i = 0; i < numskins; i++) + { + if (R_SkinUsable(playernum, i)) + { + return i; + } + } + + I_Error("All characters are locked!"); + return 0; +} + // network code calls this when a 'skin change' is received void SetPlayerSkin(INT32 playernum, const char *skinname) { @@ -224,16 +403,16 @@ void SetPlayerSkin(INT32 playernum, const char *skinname) if ((i != -1) && R_SkinUsable(playernum, i)) { - SetPlayerSkinByNum(playernum, i); + SetSkin(player, i); return; } if (P_IsLocalPlayer(player)) CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); - else if(server || IsPlayerAdmin(consoleplayer)) + else if (server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); - SetPlayerSkinByNum(playernum, 0); + SetSkin(player, GetPlayerDefaultSkin(playernum)); } // Same as SetPlayerSkin, but uses the skin #. @@ -241,90 +420,19 @@ void SetPlayerSkin(INT32 playernum, const char *skinname) void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) { player_t *player = &players[playernum]; - skin_t *skin = &skins[skinnum]; - UINT16 newcolor = 0; if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists! { - player->skin = skinnum; - - player->camerascale = skin->camerascale; - player->shieldscale = skin->shieldscale; - - player->charability = (UINT8)skin->ability; - player->charability2 = (UINT8)skin->ability2; - - player->charflags = (UINT32)skin->flags; - - player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; - player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; - player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; - player->followitem = skin->followitem; - - if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff. - player->powers[pw_shield] &= SH_STACK; - - player->actionspd = skin->actionspd; - player->mindash = skin->mindash; - player->maxdash = skin->maxdash; - - player->normalspeed = skin->normalspeed; - player->runspeed = skin->runspeed; - player->thrustfactor = skin->thrustfactor; - player->accelstart = skin->accelstart; - player->acceleration = skin->acceleration; - - player->jumpfactor = skin->jumpfactor; - - player->height = skin->height; - player->spinheight = skin->spinheight; - - if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) - { - if (playernum == consoleplayer) - CV_StealthSetValue(&cv_playercolor, skin->prefcolor); - else if (playernum == secondarydisplayplayer) - CV_StealthSetValue(&cv_playercolor2, skin->prefcolor); - player->skincolor = newcolor = skin->prefcolor; - if (player->bot && botingame) - { - botskin = (UINT8)(skinnum + 1); - botcolor = skin->prefcolor; - } - } - - if (player->followmobj) - { - P_RemoveMobj(player->followmobj); - P_SetTarget(&player->followmobj, NULL); - } - - if (player->mo) - { - fixed_t radius = FixedMul(skin->radius, player->mo->scale); - if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. - { - skin = &skins[DEFAULTNIGHTSSKIN]; - player->followitem = skin->followitem; - if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) - newcolor = skin->prefcolor; // will be updated in thinker to flashing - } - player->mo->skin = skin; - if (newcolor) - player->mo->color = newcolor; - P_SetScale(player->mo, player->mo->scale); - player->mo->radius = radius; - - P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames - } + SetSkin(player, skinnum); return; } if (P_IsLocalPlayer(player)) CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum); - else if(server || IsPlayerAdmin(consoleplayer)) + else if (server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); - SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin + + SetSkin(player, GetPlayerDefaultSkin(playernum)); } // @@ -558,7 +666,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) // // Find skin sprites, sounds & optional status bar face, & add them // -void R_AddSkins(UINT16 wadnum) +void R_AddSkins(UINT16 wadnum, boolean mainfile) { UINT16 lump, lastlump = 0; char *buf; @@ -673,12 +781,6 @@ void R_AddSkins(UINT16 wadnum) if (!realname) STRBUFCPY(skin->realname, skin->hudname); } - else if (!stricmp(stoken, "availability")) - { - skin->availability = atoi(value); - if (skin->availability >= MAXUNLOCKABLES) - skin->availability = 0; - } else if (!R_ProcessPatchableFields(skin, stoken, value)) CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); @@ -693,7 +795,7 @@ next_token: R_FlushTranslationColormapCache(); - if (!skin->availability) // Safe to print... + if (mainfile == false) CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); #ifdef SKINVALUES skin_cons_t[numskins].value = numskins; @@ -713,7 +815,7 @@ next_token: // // Patch skin sprites // -void R_PatchSkins(UINT16 wadnum) +void R_PatchSkins(UINT16 wadnum, boolean mainfile) { UINT16 lump, lastlump = 0; char *buf; @@ -826,7 +928,7 @@ next_token: R_FlushTranslationColormapCache(); - if (!skin->availability) // Safe to print... + if (mainfile == false) CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); } return; diff --git a/src/r_skins.h b/src/r_skins.h index fbbb38743..a38997f4d 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -80,8 +80,6 @@ typedef struct // contains super versions too spritedef_t sprites[NUMPLAYERSPRITES*2]; spriteinfo_t sprinfo[NUMPLAYERSPRITES*2]; - - UINT8 availability; // lock? } skin_t; /// Externs @@ -91,13 +89,14 @@ extern skin_t skins[MAXSKINS]; /// Function prototypes void R_InitSkins(void); +INT32 GetPlayerDefaultSkin(INT32 playernum); void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 boolean R_SkinUsable(INT32 playernum, INT32 skinnum); UINT32 R_GetSkinAvailabilities(void); INT32 R_SkinAvailable(const char *name); -void R_PatchSkins(UINT16 wadnum); -void R_AddSkins(UINT16 wadnum); +void R_AddSkins(UINT16 wadnum, boolean mainfile); +void R_PatchSkins(UINT16 wadnum, boolean mainfile); UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); diff --git a/src/r_sky.c b/src/r_sky.c index 7cdcfa44d..041cccfc5 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_sky.h b/src/r_sky.h index 55d866b86..f4356dcfa 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_splats.c b/src/r_splats.c index a3fad82d8..4783fb640 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,11 +28,12 @@ static void prepare_rastertab(void); // FLOOR SPLATS // ========================================================================== +static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); + #ifdef USEASM void ASMCALL rasterize_segment_tex_asm(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir); #endif -// Lactozilla static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir) { #ifdef USEASM @@ -137,7 +138,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 } } -void R_DrawFloorSprite(vissprite_t *spr) +void R_DrawFloorSplat(vissprite_t *spr) { floorsplat_t splat; mobj_t *mobj = spr->mobj; @@ -187,7 +188,7 @@ void R_DrawFloorSprite(vissprite_t *spr) if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) splatangle = mobj->angle; else - splatangle = viewangle; + splatangle = spr->viewangle; if (!(spr->cut & SC_ISROTATED)) splatangle += mobj->rollangle; @@ -265,7 +266,6 @@ void R_DrawFloorSprite(vissprite_t *spr) if (splat.tilted) { - // Lactozilla: Just copy the entire slope LMFAOOOO pslope_t *s = &splat.slope; s->o.x = slope->o.x; @@ -330,7 +330,7 @@ void R_DrawFloorSprite(vissprite_t *spr) v2d[i].y = (centeryfrac + FixedMul(rot_z, yscale))>>FRACBITS; } - R_RenderFloorSplat(&splat, v2d, spr); + R_RasterizeFloorSplat(&splat, v2d, spr); } // -------------------------------------------------------------------------- @@ -338,7 +338,7 @@ void R_DrawFloorSprite(vissprite_t *spr) // fill the polygon with linear interpolation, call span drawer for each // scan line // -------------------------------------------------------------------------- -void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis) +static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis) { // rasterizing INT32 miny = viewheight + 1, maxy = 0; @@ -416,11 +416,11 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis if (R_CheckPowersOfTwo()) R_CheckFlatLength(ds_flatwidth * ds_flatheight); - // Lactozilla: I don't know what I'm doing if (pSplat->tilted) { R_SetTiltedSpan(0); - R_CalculateSlopeVectors(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, viewangle, pSplat->angle, 1.0f); + R_SetScaledSlopePlane(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle); + R_CalculateSlopeVectors(); spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; } else @@ -533,7 +533,7 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis fixed_t xstep, ystep; fixed_t distance, span; - angle_t angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT; + angle_t angle = (vis->viewangle + pSplat->angle)>>ANGLETOFINESHIFT; angle_t planecos = FINECOSINE(angle); angle_t planesin = FINESINE(angle); @@ -543,17 +543,13 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); span = abs(centery - y); - if (span) // don't divide by zero + if (span) // Don't divide by zero { xstep = FixedMul(planesin, planeheight) / span; ystep = FixedMul(planecos, planeheight) / span; } else - { - // ah - xstep = FRACUNIT; - ystep = FRACUNIT; - } + xstep = ystep = FRACUNIT; cachedxstep[y] = xstep; cachedystep[y] = ystep; diff --git a/src/r_splats.h b/src/r_splats.h index e1f836f48..cab3d63b6 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -42,7 +42,6 @@ typedef struct floorsplat_s mobj_t *mobj; // Mobj it is tied to } floorsplat_t; -void R_DrawFloorSprite(vissprite_t *spr); -void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis); +void R_DrawFloorSplat(vissprite_t *spr); #endif /*__R_SPLATS_H__*/ diff --git a/src/r_state.h b/src/r_state.h index 25aa69702..5a606ed8c 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_textures.c b/src/r_textures.c index 0a1248100..793e5237f 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,11 +28,6 @@ #include "byteptr.h" #include "dehacked.h" -// I don't know what this is even for, but r_data.c had it. -#ifdef _WIN32 -#include // alloca(sizeof) -#endif - #ifdef HWRENDER #include "hardware/hw_glob.h" // HWR_LoadMapTextures #endif @@ -626,7 +621,7 @@ void *R_GetLevelFlat(levelflat_t *levelflat) // // R_CheckPowersOfTwo // -// Self-explanatory? +// Sets ds_powersoftwo true if the flat's dimensions are powers of two, and returns that. // boolean R_CheckPowersOfTwo(void) { diff --git a/src/r_textures.h b/src/r_textures.h index 74a94a9ed..dd286b6ac 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_things.c b/src/r_things.c index 135c4c5bf..b636a9701 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -230,7 +230,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 UINT8 rotation; lumpinfo_t *lumpinfo; softwarepatch_t patch; - UINT8 numadded = 0; + UINT16 numadded = 0; memset(sprtemp,0xFF, sizeof (sprtemp)); maxframe = (size_t)-1; @@ -548,8 +548,8 @@ void R_InitSprites(void) R_InitSkins(); for (i = 0; i < numwadfiles; i++) { - R_AddSkins((UINT16)i); - R_PatchSkins((UINT16)i); + R_AddSkins((UINT16)i, true); + R_PatchSkins((UINT16)i, true); R_LoadSpriteInfoLumps(i, wadfiles[i]->numlumps); } ST_ReloadSkinFaceGraphics(); @@ -754,7 +754,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) else if (vis->mobj->type == MT_METALSONIC_BATTLE) return R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); else - return R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + return R_GetTranslationColormap(TC_BOSS, vis->mobj->color, GTC_CACHE); } else if (vis->mobj->color) { @@ -1804,7 +1804,7 @@ static void R_ProjectSprite(mobj_t *thing) else if (oldthing->frame & FF_TRANSMASK) { trans = (oldthing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; - if (oldthing->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS) + if (!R_BlendLevelVisible(oldthing->blendmode, trans)) return; } else @@ -1957,6 +1957,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->paperoffset = paperoffset; vis->paperdistance = paperdistance; vis->centerangle = centerangle; + vis->viewangle = viewangle; vis->shear.tan = sheartan; vis->shear.offset = 0; @@ -2200,7 +2201,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // specific translucency if (thing->frame & FF_TRANSMASK) - vis->transmap = (thing->frame & FF_TRANSMASK) - 0x10000 + transtables; + vis->transmap = R_GetTranslucencyTable((thing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT); else vis->transmap = NULL; @@ -2784,7 +2785,7 @@ static void R_DrawSprite(vissprite_t *spr) mceilingclip = spr->cliptop; if (spr->cut & SC_SPLAT) - R_DrawFloorSprite(spr); + R_DrawFloorSplat(spr); else R_DrawVisSprite(spr); } diff --git a/src/r_things.h b/src/r_things.h index 708b6c24c..9315b36e9 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -164,6 +164,7 @@ typedef struct vissprite_s fixed_t xiscale; // negative if flipped angle_t centerangle; // for paper sprites + angle_t viewangle; // for floor sprites, the viewpoint's current angle struct { fixed_t tan; // The amount to shear the sprite vertically per row diff --git a/src/s_sound.c b/src/s_sound.c index 392a5b453..30f242369 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1033,11 +1033,9 @@ void S_SetSfxVolume(INT32 volume) void S_ClearSfx(void) { -#ifndef DJGPPDOS size_t i; for (i = 1; i < NUMSFX; i++) I_FreeSfx(S_sfx + i); -#endif } static void S_StopChannel(INT32 cnum) @@ -1354,28 +1352,6 @@ void S_InitSfxChannels(INT32 sfxVolume) /// Music /// ------------------------ -#ifdef MUSICSLOT_COMPATIBILITY -const char *compat_special_music_slots[16] = -{ - "_title", // 1036 title screen - "_intro", // 1037 intro - "_clear", // 1038 level clear - "_inv", // 1039 invincibility - "_shoes", // 1040 super sneakers - "_minv", // 1041 Mario invincibility - "_drown", // 1042 drowning - "_gover", // 1043 game over - "_1up", // 1044 extra life - "_conti", // 1045 continue screen - "_super", // 1046 Super Sonic - "_chsel", // 1047 character select - "_creds", // 1048 credits - "_inter", // 1049 Race Results - "_stjr", // 1050 Sonic Team Jr. Presents - "" -}; -#endif - static char music_name[7]; // up to 6-character name static void *music_data; static UINT16 music_flags; @@ -2262,6 +2238,16 @@ static void S_ChangeMusicToQueue(void) void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms) { char newmusic[7]; + + struct MusicChange hook_param = { + newmusic, + &mflags, + &looping, + &position, + &prefadems, + &fadeinms + }; + boolean currentmidi = (I_SongType() == MU_MID || I_SongType() == MU_MID_EX); boolean midipref = cv_musicpref.value; @@ -2269,7 +2255,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 return; strncpy(newmusic, mmusic, 7); - if (LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) + if (LUA_HookMusicChange(music_name, &hook_param)) return; newmusic[6] = 0; @@ -2465,7 +2451,7 @@ void S_StartEx(boolean reset) static void Command_Tunes_f(void) { const char *tunearg; - UINT16 tunenum, track = 0; + UINT16 track = 0; UINT32 position = 0; const size_t argc = COM_Argc(); @@ -2481,7 +2467,6 @@ static void Command_Tunes_f(void) } tunearg = COM_Argv(1); - tunenum = (UINT16)atoi(tunearg); track = 0; if (!strcasecmp(tunearg, "-show")) @@ -2500,24 +2485,14 @@ static void Command_Tunes_f(void) tunearg = mapheaderinfo[gamemap-1]->musname; track = mapheaderinfo[gamemap-1]->mustrack; } - else if (!tunearg[2] && toupper(tunearg[0]) >= 'A' && toupper(tunearg[0]) <= 'Z') - tunenum = (UINT16)M_MapNumber(tunearg[0], tunearg[1]); - if (tunenum && tunenum >= 1036) - { - CONS_Alert(CONS_NOTICE, M_GetText("Valid music slots are 1 to 1035.\n")); - return; - } - if (!tunenum && strlen(tunearg) > 6) // This is automatic -- just show the error just in case + if (strlen(tunearg) > 6) // This is automatic -- just show the error just in case CONS_Alert(CONS_NOTICE, M_GetText("Music name too long - truncated to six characters.\n")); if (argc > 2) track = (UINT16)atoi(COM_Argv(2))-1; - if (tunenum) - snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum)); - else - strncpy(mapmusname, tunearg, 7); + strncpy(mapmusname, tunearg, 7); if (argc > 4) position = (UINT32)atoi(COM_Argv(4)); diff --git a/src/s_sound.h b/src/s_sound.h index 4ac3c70bf..8fcb816d9 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -265,6 +265,16 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst); // Music Playback // +/* this is for the sake of the hook */ +struct MusicChange { + char * newname; + UINT16 * mflags; + boolean * looping; + UINT32 * position; + UINT32 * prefadems; + UINT32 * fadeinms; +}; + // Start music track, arbitrary, given its name, and set whether looping // note: music flags 12 bits for tracknum (gme, other formats with more than one track) // 13-15 aren't used yet @@ -319,10 +329,4 @@ void S_StopSoundByNum(sfxenum_t sfxnum); #define S_StartScreamSound S_StartSound #endif -#ifdef MUSICSLOT_COMPATIBILITY -// For compatibility with code/scripts relying on older versions -// This is a list of all the "special" slot names and their associated numbers -extern const char *compat_special_music_slots[16]; -#endif - #endif diff --git a/src/screen.c b/src/screen.c index 744523dab..770f1c802 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -33,6 +33,11 @@ #include "s_sound.h" // ditto #include "g_game.h" // ditto #include "p_local.h" // P_AutoPause() +#ifdef HWRENDER +#include "hardware/hw_main.h" +#include "hardware/hw_light.h" +#include "hardware/hw_model.h" +#endif #if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200)) @@ -423,6 +428,10 @@ void SCR_ChangeRenderer(void) CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); return; } + + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) // Clear these out before switching to software + HWR_ClearAllTextures(); + #endif // Set the new render mode diff --git a/src/screen.h b/src/screen.h index e4944775d..67880e2b9 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index a7f015c86..4f19d93df 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -21,46 +21,25 @@ if(${SRB2_CONFIG_SDL2_USEMIXER}) endif() if(${SDL2_MIXER_FOUND}) set(SRB2_HAVE_MIXER ON) - set(SRB2_SDL2_SOUNDIMPL mixer_sound.c) + target_sources(SRB2SDL2 PRIVATE mixer_sound.c) else() message(WARNING "You specified that SDL2_mixer is available, but it was not found. Falling back to sdl sound.") - set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) + target_sources(SRB2SDL2 PRIVATE sdl_sound.c) endif() elseif(${MIXERX_FOUND}) - set(SRB2_SDL2_SOUNDIMPL mixer_sound.c) + target_sources(SRB2SDL2 PRIVATE mixer_sound.c) else() - set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) + target_sources(SRB2SDL2 PRIVATE sdl_sound.c) endif() -set(SRB2_SDL2_SOURCES - dosstr.c - endtxt.c - hwsym_sdl.c - i_main.c - i_net.c - i_system.c - i_ttf.c - i_video.c - #IMG_xpm.c - ogl_sdl.c +target_sourcefile(c) - ${SRB2_SDL2_SOUNDIMPL} -) - -set(SRB2_SDL2_HEADERS - endtxt.h - hwsym_sdl.h - i_ttf.h - ogl_sdl.h - sdlmain.h -) +target_sources(SRB2SDL2 PRIVATE ogl_sdl.c) if(${SRB2_CONFIG_HAVE_THREADS}) - set(SRB2_SDL2_SOURCES ${SRB2_SDL2_SOURCES} i_threads.c) + target_sources(SRB2SDL2 PRIVATE i_threads.c) endif() -source_group("Interface Code" FILES ${SRB2_SDL2_SOURCES} ${SRB2_SDL2_HEADERS}) - # Dependency if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) set(SDL2_FOUND ON) @@ -76,79 +55,29 @@ else() endif() if(${SDL2_FOUND}) - set(SRB2_SDL2_TOTAL_SOURCES - ${SRB2_CORE_SOURCES} - ${SRB2_CORE_HEADERS} - ${SRB2_PNG_SOURCES} - ${SRB2_PNG_HEADERS} - ${SRB2_CORE_RENDER_SOURCES} - ${SRB2_CORE_GAME_SOURCES} - ${SRB2_LUA_SOURCES} - ${SRB2_LUA_HEADERS} - ${SRB2_BLUA_SOURCES} - ${SRB2_BLUA_HEADERS} - ${SRB2_SDL2_SOURCES} - ${SRB2_SDL2_HEADERS} - ) - - source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS} - ${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS}) - source_group("Renderer" FILES ${SRB2_CORE_RENDER_SOURCES}) - source_group("Game" FILES ${SRB2_CORE_GAME_SOURCES}) - source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES}) - source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS}) - source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS}) - - if(${SRB2_CONFIG_HWRENDER}) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${SRB2_HWRENDER_SOURCES} - ${SRB2_HWRENDER_HEADERS} - ${SRB2_R_OPENGL_SOURCES} - ${SRB2_R_OPENGL_HEADERS} - ) - - source_group("Hardware" FILES ${SRB2_HWRENDER_SOURCES} ${SRB2_HWRENDER_HEADERS}) - source_group("Hardware\\OpenGL Renderer" FILES ${SRB2_R_OPENGL_SOURCES} ${SRB2_R_OPENGL_HEADERS}) - endif() - if(${SRB2_USEASM}) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${SRB2_NASM_SOURCES} - ) - if(MSVC) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${SRB2_NASM_OBJECTS} - ) - set_source_files_properties(${SRB2_NASM_OBJECTS} PROPERTIES GENERATED ON) - else() - list(APPEND SRB2_SDL2_TOTAL_SOURCES ${SRB2_ASM_SOURCES}) - set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES LANGUAGE C) - set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") - endif() + set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES LANGUAGE C) + set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") endif() if(${CMAKE_SYSTEM} MATCHES Windows) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${CMAKE_SOURCE_DIR}/src/win32/win_dbg.c - ${CMAKE_SOURCE_DIR}/src/win32/Srb2win.rc - ) + target_sources(SRB2SDL2 PRIVATE + ../win32/win_dbg.c + ../win32/Srb2win.rc) endif() if(${CMAKE_SYSTEM} MATCHES Darwin) set(MACOSX_BUNDLE_ICON_FILE Srb2mac.icns) set_source_files_properties(macosx/Srb2mac.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") - set(SRB2_SDL2_MAC_SOURCES + target_sources(SRB2SDL2 PRIVATE macosx/mac_alert.c macosx/mac_alert.h macosx/mac_resources.c macosx/mac_resources.h macosx/Srb2mac.icns ) - source_group("Interface Code\\OSX Compatibility" FILES ${SRB2_SDL2_MAC_SOURCES}) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} ${SRB2_SDL2_MAC_SOURCES}) endif() - add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 ${SRB2_SDL2_TOTAL_SOURCES}) if(${CMAKE_SYSTEM} MATCHES Windows) set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2win) elseif(${CMAKE_SYSTEM} MATCHES Linux) @@ -205,18 +134,6 @@ if(${SDL2_FOUND}) set(ASM_ASSEMBLER_OBJFORMAT ${CMAKE_ASM_NASM_OBJECT_FORMAT}) set_source_files_properties(${SRB2_NASM_SOURCES} LANGUAGE ASM_NASM) endif() - - if(MSVC) - # using assembler with msvc doesn't work, must do it manually - foreach(ASMFILE ${SRB2_NASM_SOURCES}) - get_filename_component(ASMFILE_NAME ${ASMFILE} NAME_WE) - set(ASMFILE_NAME ${ASMFILE_NAME}.obj) - add_custom_command(TARGET SRB2SDL2 PRE_LINK - COMMAND ${ASM_ASSEMBLER_TEMP} ARGS -f ${ASM_ASSEMBLER_OBJFORMAT} -o ${CMAKE_CURRENT_BINARY_DIR}/${ASMFILE_NAME} ${ASMFILE} - COMMENT "assemble ${ASMFILE_NAME}." - ) - endforeach() - endif() endif() set_target_properties(SRB2SDL2 PROPERTIES VERSION ${SRB2_VERSION}) @@ -230,31 +147,6 @@ if(${SDL2_FOUND}) ) endif() - if(MSVC) - if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) - set(SDL2_MAIN_FOUND ON) - if(${SRB2_SYSTEM_BITS} EQUAL 64) - set(SDL2_MAIN_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/include/SDL2) - set(SDL2_MAIN_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/lib -lSDL2main") - else() # 32-bit - set(SDL2_MAIN_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/include/SDL2) - set(SDL2_MAIN_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/lib -lSDL2main") - endif() - else() - find_package(SDL2_MAIN REQUIRED) - endif() - target_link_libraries(SRB2SDL2 PRIVATE - ${SDL2_MAIN_LIBRARIES} - ) - target_compile_options(SRB2SDL2 PRIVATE - /Umain - /D_CRT_SECURE_NO_WARNINGS # something about string functions. - /D_CRT_NONSTDC_NO_DEPRECATE - /DSDLMAIN - /D_WINSOCK_DEPRECATED_NO_WARNINGS # Don't care - ) - endif() - target_include_directories(SRB2SDL2 PRIVATE ${SDL2_INCLUDE_DIRS} ${SDL2_MIXER_INCLUDE_DIRS} diff --git a/src/sdl/MakeNIX.cfg b/src/sdl/MakeNIX.cfg deleted file mode 100644 index 47c944eb5..000000000 --- a/src/sdl/MakeNIX.cfg +++ /dev/null @@ -1,74 +0,0 @@ -# -# sdl/makeNIX.cfg for SRB2/?nix -# - -#Valgrind support -ifdef VALGRIND -VALGRIND_PKGCONFIG?=valgrind -VALGRIND_CFLAGS?=$(shell $(PKG_CONFIG) $(VALGRIND_PKGCONFIG) --cflags) -VALGRIND_LDFLAGS?=$(shell $(PKG_CONFIG) $(VALGRIND_PKGCONFIG) --libs) -ZDEBUG=1 -LIBS+=$(VALGRIND_LDFLAGS) -ifdef GCC46 -WFLAGS+=-Wno-error=unused-but-set-variable -WFLAGS+=-Wno-unused-but-set-variable -endif -endif - -# -#here is GNU/Linux and other -# - - OPTS=-DUNIXCOMMON - - #LDFLAGS = -L/usr/local/lib - LIBS=-lm -ifdef LINUX - LIBS+=-lrt -ifdef NOTERMIOS - OPTS+=-DNOTERMIOS -endif -endif - -ifdef LINUX64 - OPTS+=-DLINUX64 -endif - -# -#here is Solaris -# -ifdef SOLARIS - NOIPX=1 - NOASM=1 - OPTS+=-DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP - OPTS+=-I/usr/local/include -I/opt/sfw/include - LDFLAGS+=-L/opt/sfw/lib - LIBS+=-lsocket -lnsl -endif - -# -#here is FreeBSD -# -ifdef FREEBSD - OPTS+=-DLINUX -DFREEBSD -I/usr/X11R6/include - SDL_CONFIG?=sdl11-config - LDFLAGS+=-L/usr/X11R6/lib - LIBS+=-lipx -lkvm -endif - -# -#here is Mac OS X -# -ifdef MACOSX - OBJS+=$(OBJDIR)/mac_resources.o - OBJS+=$(OBJDIR)/mac_alert.o - LIBS+=-framework CoreFoundation -endif - -ifndef NOHW - OPTS+=-I/usr/X11R6/include - LDFLAGS+=-L/usr/X11R6/lib -endif - - # name of the exefile - EXENAME?=lsdl2srb2 diff --git a/src/sdl/Makefile.cfg b/src/sdl/Makefile.cfg deleted file mode 100644 index 45d0d6ba7..000000000 --- a/src/sdl/Makefile.cfg +++ /dev/null @@ -1,125 +0,0 @@ -# -# sdl/makefile.cfg for SRB2/SDL -# - -# -#SDL...., *looks at Alam*, THIS IS A MESS! -# - -ifdef UNIXCOMMON -include sdl/MakeNIX.cfg -endif - -ifdef PANDORA -include sdl/SRB2Pandora/Makefile.cfg -endif #ifdef PANDORA - -ifdef CYGWIN32 -include sdl/MakeCYG.cfg -endif #ifdef CYGWIN32 - -ifdef SDL_PKGCONFIG -SDL_CFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --cflags) -SDL_LDFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --libs) -else -ifdef PREFIX - SDL_CONFIG?=$(PREFIX)-sdl2-config -else - SDL_CONFIG?=sdl2-config -endif - -ifdef STATIC - SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) - SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --static-libs) -else - SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) - SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --libs) -endif -endif - - - #use the x86 asm code -ifndef CYGWIN32 -ifndef NOASM - USEASM=1 -endif -endif - - OBJS+=$(OBJDIR)/i_video.o $(OBJDIR)/dosstr.o $(OBJDIR)/endtxt.o $(OBJDIR)/hwsym_sdl.o - - OPTS+=-DDIRECTFULLSCREEN -DHAVE_SDL - -ifndef NOHW - OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/ogl_sdl.o -endif - -ifdef NOMIXER - i_sound_o=$(OBJDIR)/sdl_sound.o -else - i_sound_o=$(OBJDIR)/mixer_sound.o - OPTS+=-DHAVE_MIXER -ifdef HAVE_MIXERX - OPTS+=-DHAVE_MIXERX - SDL_LDFLAGS+=-lSDL2_mixer_ext -else - SDL_LDFLAGS+=-lSDL2_mixer -endif -endif - -ifndef NOTHREADS - OPTS+=-DHAVE_THREADS - OBJS+=$(OBJDIR)/i_threads.o -endif - -ifdef SDL_TTF - OPTS+=-DHAVE_TTF - SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz - OBJS+=$(OBJDIR)/i_ttf.o -endif - -ifdef SDL_IMAGE - OPTS+=-DHAVE_IMAGE - SDL_LDFLAGS+=-lSDL2_image -endif - -ifdef SDL_NET - OPTS+=-DHAVE_SDLNET - SDL_LDFLAGS+=-lSDL2_net -endif - -ifdef MINGW -ifndef NOSDLMAIN - SDLMAIN=1 -endif -endif - -ifdef SDLMAIN - OPTS+=-DSDLMAIN -else -ifdef MINGW - SDL_CFLAGS+=-Umain - SDL_LDFLAGS+=-mconsole -endif -endif - -ifndef NOHW -ifdef OPENAL -ifdef MINGW - LIBS:=-lopenal32 $(LIBS) -else - LIBS:=-lopenal $(LIBS) -endif -else -ifdef MINGW -ifdef DS3D - LIBS:=-ldsound -luuid $(LIBS) -endif -endif -endif -endif - -CFLAGS+=$(SDL_CFLAGS) -LIBS:=$(SDL_LDFLAGS) $(LIBS) -ifdef STATIC - LIBS+=$(shell $(SDL_CONFIG) --static-libs) -endif diff --git a/src/sdl/Sourcefile b/src/sdl/Sourcefile new file mode 100644 index 000000000..82d5ce073 --- /dev/null +++ b/src/sdl/Sourcefile @@ -0,0 +1,7 @@ +i_net.c +i_system.c +i_main.c +i_video.c +dosstr.c +endtxt.c +hwsym_sdl.c diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index d46a4af2b..105e1def8 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -247,6 +247,7 @@ + @@ -406,6 +407,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index adae2f446..404890397 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -402,6 +402,9 @@ P_Play + + R_Rend + R_Rend @@ -720,6 +723,9 @@ LUA + + LUA + LUA diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e8c5d59fb..d68e3e435 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -5,7 +5,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 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 @@ -102,7 +102,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #endif -#if (defined (__unix__) && !defined (_MSDOS)) || (defined (UNIXCOMMON) && !defined(__APPLE__)) +#if defined (__unix__) || (defined (UNIXCOMMON) && !defined (__APPLE__)) #include #include #define NEWSIGNALHANDLER @@ -140,6 +140,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #include #include +#define UNIXBACKTRACE #endif // Locations for searching the srb2.pk3 @@ -243,6 +244,7 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; +#ifdef UNIXBACKTRACE #define STDERR_WRITE(string) if (fd != -1) I_OutputMsg("%s", string) #define CRASHLOG_WRITE(string) if (fd != -1) write(fd, string, strlen(string)) #define CRASHLOG_STDERR_WRITE(string) \ @@ -252,7 +254,6 @@ UINT8 keyboard_started = false; static void write_backtrace(INT32 signal) { -#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) int fd = -1; size_t size; time_t rawtime; @@ -302,11 +303,11 @@ static void write_backtrace(INT32 signal) CRASHLOG_WRITE("\n"); // Write another newline to the log so it looks nice :) close(fd); -#endif } #undef STDERR_WRITE #undef CRASHLOG_WRITE #undef CRASHLOG_STDERR_WRITE +#endif // UNIXBACKTRACE static void I_ReportSignal(int num, int coredumped) { @@ -367,7 +368,9 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { D_QuitNetGame(); // Fix server freezes CL_AbortDownloadResume(); +#ifdef UNIXBACKTRACE write_backtrace(num); +#endif I_ReportSignal(num, 0); I_ShutdownSystem(); signal(num, SIG_DFL); //default signal action @@ -761,7 +764,9 @@ static void I_RegisterSignals (void) #ifdef NEWSIGNALHANDLER static void signal_handler_child(INT32 num) { +#ifdef UNIXBACKTRACE write_backtrace(num); +#endif signal(num, SIG_DFL); //default signal action raise(num); @@ -1964,7 +1969,7 @@ void I_GetMouseEvents(void) event.data1 = 0; // event.data1 = buttons; // not needed event.data2 = handlermouse2x << 1; - event.data3 = -handlermouse2y << 1; + event.data3 = handlermouse2y << 1; handlermouse2x = 0; handlermouse2y = 0; diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index 3b1c20b9a..f73d00bcf 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 0ed10463f..819589eaf 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -4,7 +4,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 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 @@ -405,6 +405,19 @@ void I_UpdateMouseGrab(void) SDLdoGrabMouse(); } +boolean I_GetMouseGrab(void) +{ + return (boolean)SDL_GetWindowGrab(window); +} + +void I_SetMouseGrab(boolean grab) +{ + if (grab) + SDLdoGrabMouse(); + else + SDLdoUngrabMouse(); +} + static void VID_Command_NumModes_f (void) { CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes()); @@ -673,8 +686,8 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) { if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window) { - mousemovex += evt.xrel; - mousemovey += -evt.yrel; + mousemovex += evt.xrel; + mousemovey += evt.yrel; SDL_SetWindowGrab(window, SDL_TRUE); } firstmove = false; @@ -1057,7 +1070,7 @@ void I_GetEvent(void) M_SetupJoystickMenu(0); break; case SDL_QUIT: - LUAh_GameQuit(true); + LUA_HookBool(true, HOOK(GameQuit)); I_Quit(); break; } @@ -1938,3 +1951,8 @@ void I_ShutdownGraphics(void) framebuffer = SDL_FALSE; } #endif + +void I_GetCursorPosition(INT32 *x, INT32 *y) +{ + SDL_GetMouseState(x, y); +} diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 412a21ea0..2f1a87266 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1301,7 +1301,7 @@ boolean I_PlaySong(boolean looping) #if defined (GME_VERSION) && GME_VERSION >= 0x000603 if (looping) gme_set_autoload_playback_limit(gme, 0); -#endif +#endif gme_set_equalizer(gme, &eq); gme_start_track(gme, 0); current_track = 0; diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 52727c056..c426e6792 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 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 diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 748e30bae..8f87f688e 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 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 diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 86e294fb5..058b601c3 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 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 diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index e35506114..a9676b5c2 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 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 diff --git a/src/sounds.c b/src/sounds.c index 092bda21f..4c5b11ee9 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sounds.h b/src/sounds.h index e49dd2f3e..2dd37953c 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/st_stuff.c b/src/st_stuff.c index 649644620..af14118e3 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -299,10 +299,6 @@ void ST_LoadGraphics(void) gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX); tagico = W_CachePatchName("TAGICO", PU_HUDGFX); - rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); - bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); - rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); - bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX); gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX); fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX); @@ -1371,7 +1367,7 @@ void ST_drawTitleCard(void) zzticker = lt_ticker; V_DrawMappedPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap); V_DrawMappedPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap); - V_DrawMappedPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); + V_DrawMappedPatch(FixedInt(lt_zigzag), (-zztext->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); V_DrawMappedPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); } @@ -2363,27 +2359,29 @@ static inline void ST_drawRaceHUD(void) static void ST_drawTeamHUD(void) { - patch_t *p; #define SEP 20 if (F_GetPromptHideHud(0)) // y base is 0 return; - if (gametyperules & GTR_TEAMFLAGS) - p = bflagico; - else - p = bmatcico; + rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); + bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); + rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); + bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); if (LUA_HudEnabled(hud_teamscores)) - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (p->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); - - if (gametyperules & GTR_TEAMFLAGS) - p = rflagico; - else - p = rmatcico; - - if (LUA_HudEnabled(hud_teamscores)) - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (p->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); + { + if (gametyperules & GTR_TEAMFLAGS) + { + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bflagico); + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rflagico); + } + else + { + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmatcico); + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmatcico); + } + } if (!(gametyperules & GTR_TEAMFLAGS)) goto num; diff --git a/src/st_stuff.h b/src/st_stuff.h index 4ea307d2b..b1ea2942d 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/strcasestr.c b/src/strcasestr.c index b266278ed..1cbee286a 100644 --- a/src/strcasestr.c +++ b/src/strcasestr.c @@ -2,7 +2,7 @@ strcasestr -- case insensitive substring searching function. */ /* -Copyright 2019-2020 James R. +Copyright 2019-2021 James R. All rights reserved. Redistribution and use in source forms, with or without modification, is diff --git a/src/string.c b/src/string.c index e430c5cc3..f32025612 100644 --- a/src/string.c +++ b/src/string.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tables.c b/src/tables.c index 70a1ecd0a..9263f42d3 100644 --- a/src/tables.c +++ b/src/tables.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tables.h b/src/tables.h index 953d891ce..baa3adf36 100644 --- a/src/tables.h +++ b/src/tables.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/taglist.c b/src/taglist.c index a759f4d02..ad1b9dc4b 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by Nev3r. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,11 +27,13 @@ taggroup_t* tags_sectors[MAXTAGS + 1]; taggroup_t* tags_lines[MAXTAGS + 1]; taggroup_t* tags_mapthings[MAXTAGS + 1]; -/// Adds a tag to a given element's taglist. +/// Adds a tag to a given element's taglist. It will not add a duplicate. /// \warning This does not rebuild the global taggroups, which are used for iteration. void Tag_Add (taglist_t* list, const mtag_t tag) { - list->tags = Z_Realloc(list->tags, (list->count + 1) * sizeof(list->tags), PU_LEVEL, NULL); + if (Tag_Find(list, tag)) + return; + list->tags = Z_Realloc(list->tags, (list->count + 1) * sizeof(mtag_t), PU_LEVEL, NULL); list->tags[list->count++] = tag; } diff --git a/src/taglist.h b/src/taglist.h index a0529ab6b..d045eb827 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by Nev3r. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -71,25 +71,16 @@ INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p); INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag); INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start); -// Use this macro to declare an iterator position variable. -#define TAG_ITER_DECLARECOUNTER(level) size_t ICNT_##level - -#define TAG_ITER(level, fn, tag, return_varname) for(ICNT_##level = 0; (return_varname = fn(tag, ICNT_##level)) >= 0; ICNT_##level++) +#define ICNAME2(id) ICNT_##id +#define ICNAME(id) ICNAME2(id) +#define TAG_ITER(fn, tag, return_varname) for(size_t ICNAME(__LINE__) = 0; (return_varname = fn(tag, ICNAME(__LINE__))) >= 0; ICNAME(__LINE__)++) // Use these macros as wrappers for a taglist iteration. -#define TAG_ITER_SECTORS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Sectors, tag, return_varname) -#define TAG_ITER_LINES(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Lines, tag, return_varname) -#define TAG_ITER_THINGS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Things, tag, return_varname) +#define TAG_ITER_SECTORS(tag, return_varname) TAG_ITER(Tag_Iterate_Sectors, tag, return_varname) +#define TAG_ITER_LINES(tag, return_varname) TAG_ITER(Tag_Iterate_Lines, tag, return_varname) +#define TAG_ITER_THINGS(tag, return_varname) TAG_ITER(Tag_Iterate_Things, tag, return_varname) /* ITERATION MACROS -TAG_ITER_DECLARECOUNTER must be used before using the iterators. - -'level': -For each nested iteration, an additional TAG_ITER_DECLARECOUNTER -must be used with a different level number to avoid conflict with -the outer iterations. -Most cases don't have nested iterations and thus the level is just 0. - 'tag': Pretty much the elements' tag to iterate through. @@ -99,17 +90,12 @@ Target variable's name to return the iteration results to. EXAMPLE: { - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_DECLARECOUNTER(1); // For the nested iteration. - size_t li; - size_t sec; - INT32 tag1 = 4; ... - TAG_ITER_LINES(0, tag1, li) + TAG_ITER_LINES(tag1, li) { line_t *line = lines + li; @@ -117,11 +103,11 @@ EXAMPLE: if (something) { + size_t sec; mtag_t tag2 = 8; - // Nested iteration; just make sure the level is higher - // and that it has its own counter declared in scope. - TAG_ITER_SECTORS(1, tag2, sec) + // Nested iteration. + TAG_ITER_SECTORS(tag2, sec) { sector_t *sector = sectors + sec; diff --git a/src/tmap.nas b/src/tmap.nas index 69282d0b4..5bf28359e 100644 --- a/src/tmap.nas +++ b/src/tmap.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2020 by Sonic Team Junior. +;; Copyright (C) 1999-2021 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap.s b/src/tmap.s index 3a4cf2e1a..62dcf85dc 100644 --- a/src/tmap.s +++ b/src/tmap.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap_asm.s b/src/tmap_asm.s index 3cd0f87cc..b5a0a51e9 100644 --- a/src/tmap_asm.s +++ b/src/tmap_asm.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap_mmx.nas b/src/tmap_mmx.nas index 15b97499d..8b6ef91a6 100644 --- a/src/tmap_mmx.nas +++ b/src/tmap_mmx.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DOSDOOM. -;; Copyright (C) 2010-2020 by Sonic Team Junior. +;; Copyright (C) 2010-2021 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap_vc.nas b/src/tmap_vc.nas index 49eb21a6d..b6ee26e6b 100644 --- a/src/tmap_vc.nas +++ b/src/tmap_vc.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2020 by Sonic Team Junior. +;; Copyright (C) 1999-2021 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/v_video.c b/src/v_video.c index 4713db0d8..de05df2d5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -418,7 +418,7 @@ void V_SetPalette(INT32 palettenum) #ifdef HWRENDER if (rendermode == render_opengl) HWR_SetPalette(&pLocalPalette[palettenum*256]); -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) else #endif #endif @@ -432,7 +432,7 @@ void V_SetPaletteLump(const char *pal) #ifdef HWRENDER if (rendermode == render_opengl) HWR_SetPalette(pLocalPalette); -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) else #endif #endif @@ -455,7 +455,8 @@ void VID_BlitLinearScreen_ASM(const UINT8 *srcptr, UINT8 *destptr, INT32 width, static void CV_constextsize_OnChange(void) { - con_recalc = true; + if (!con_refresh) + con_recalc = true; } diff --git a/src/v_video.h b/src/v_video.h index 8a18f82ad..7184e799e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/version.h b/src/version.h index ece084beb..4470fbd6e 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define SRB2VERSION "2.2.8"/* this must be the first line, for cmake !! */ +#define SRB2VERSION "2.2.9"/* this must be the first line, for cmake !! */ // The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/showgroups.php ). // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. @@ -9,7 +9,7 @@ // 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.2.0 is not version "1". -#define MODVERSION 49 +#define MODVERSION 50 // Define this as a prerelease version suffix // #define BETAVERSION "RC1" diff --git a/src/vid_copy.s b/src/vid_copy.s index eae435ea4..6a3788356 100644 --- a/src/vid_copy.s +++ b/src/vid_copy.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/w_wad.c b/src/w_wad.c index b305d89e9..e37c86bac 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -894,7 +894,10 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) } if (important && !mainfile) - G_SetGameModified(true); + { + //G_SetGameModified(true); + modifiedgame = true; // avoid savemoddata being set to false + } // // link wad file to search files diff --git a/src/w_wad.h b/src/w_wad.h index 8b3c3808e..25b4bffa8 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg deleted file mode 100644 index 702ae3765..000000000 --- a/src/win32/Makefile.cfg +++ /dev/null @@ -1,136 +0,0 @@ -# -# win32/Makefile.cfg for SRB2/Minwgw -# - -# -#Mingw, if you don't know, that's Win32/Win64 -# - -ifdef MINGW64 - HAVE_LIBGME=1 - LIBGME_CFLAGS=-I../libs/gme/include - LIBGME_LDFLAGS=-L../libs/gme/win64 -lgme -ifdef HAVE_OPENMPT - LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc - LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86_64/mingw -lopenmpt -endif -ifndef NOMIXERX - HAVE_MIXERX=1 - SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDLMixerX/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -else - SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDL2_mixer/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -endif -else - HAVE_LIBGME=1 - LIBGME_CFLAGS=-I../libs/gme/include - LIBGME_LDFLAGS=-L../libs/gme/win32 -lgme -ifdef HAVE_OPENMPT - LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc - LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86/mingw -lopenmpt -endif -ifndef NOMIXERX - HAVE_MIXERX=1 - SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDLMixerX/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -else - SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDL2_mixer/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -endif -endif - -ifndef NOASM - USEASM=1 -endif - -ifndef NONET -ifndef MINGW64 #miniupnc is broken with MINGW64 - HAVE_MINIUPNPC=1 -endif -endif - - OPTS=-DSTDC_HEADERS - -ifndef GCC44 - #OPTS+=-mms-bitfields -endif - - LIBS+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 -ifdef MINGW64 - LIBS+=-lws2_32 -else -ifdef NO_IPV6 - LIBS+=-lwsock32 -else - LIBS+=-lws2_32 -endif -endif - - # name of the exefile - EXENAME?=srb2win.exe - -ifdef SDL - i_system_o+=$(OBJDIR)/SRB2.res - #i_main_o+=$(OBJDIR)/win_dbg.o -ifndef NOHW - OPTS+=-DUSE_WGL_SWAP -endif -endif - - -ZLIB_CFLAGS?=-I../libs/zlib -ifdef MINGW64 -ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz64 -else -ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz32 -endif - -ifndef NOPNG -ifndef PNG_CONFIG - PNG_CFLAGS?=-I../libs/libpng-src -ifdef MINGW64 - PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng64 -else - PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng32 -endif #MINGW64 -endif #PNG_CONFIG -endif #NOPNG - -ifdef GETTEXT -ifndef CCBS - MSGFMT?=../libs/gettext/bin32/msgfmt.exe -endif -ifdef MINGW64 - CPPFLAGS+=-I../libs/gettext/include64 - LDFLAGS+=-L../libs/gettext/lib64 - LIBS+=-lmingwex -else - CPPFLAGS+=-I../libs/gettext/include32 - LDFLAGS+=-L../libs/gettext/lib32 - STATIC_GETTEXT=1 -endif #MINGW64 -ifdef STATIC_GETTEXT - LIBS+=-lasprintf -lintl -else - LIBS+=-lintl.dll -endif #STATIC_GETTEXT -endif #GETTEXT - -ifdef HAVE_MINIUPNPC - CPPFLAGS+=-I../libs/ -DSTATIC_MINIUPNPC -ifdef MINGW64 - LDFLAGS+=-L../libs/miniupnpc/mingw64 -else - LDFLAGS+=-L../libs/miniupnpc/mingw32 -endif #MINGW64 -endif - -ifndef NOCURL - CURL_CFLAGS+=-I../libs/curl/include -ifdef MINGW64 - CURL_LDFLAGS+=-L../libs/curl/lib64 -lcurl -else - CURL_LDFLAGS+=-L../libs/curl/lib32 -lcurl -endif #MINGW64 -endif diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index d5d59922c..0a280448b 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -76,8 +76,8 @@ END #include "../doomdef.h" // Needed for version string VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,2,8,0 - PRODUCTVERSION 2,2,8,0 + FILEVERSION 2,2,9,0 + PRODUCTVERSION 2,2,9,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -97,7 +97,7 @@ BEGIN VALUE "FileDescription", "Sonic Robo Blast 2\0" VALUE "FileVersion", VERSIONSTRING_RC VALUE "InternalName", "srb2\0" - VALUE "LegalCopyright", "Copyright 1998-2020 by Sonic Team Junior\0" + VALUE "LegalCopyright", "Copyright 1998-2021 by Sonic Team Junior\0" VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" VALUE "OriginalFilename", "srb2win.exe\0" VALUE "PrivateBuild", "\0" diff --git a/src/y_inter.c b/src/y_inter.c index bd3b557d7..6d876d7bd 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2020 by Sonic Team Junior. +// Copyright (C) 2004-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -215,6 +215,89 @@ static void Y_IntermissionTokenDrawer(void) V_DrawCroppedPatch(32<width, calc); } + +// +// Y_LoadIntermissionData +// +// Load patches for drawing the intermission, if acceptable +// +void Y_LoadIntermissionData(void) +{ + INT32 i; + + if (dedicated) + return; + + switch (intertype) + { + case int_coop: + { + for (i = 0; i < 4; ++i) + { + if (strlen(data.coop.bonuses[i].patch)) + data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_PATCH); + } + data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH); + + // get background patches + bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); + + // grab an interscreen if appropriate + if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') + interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + break; + } + case int_spec: + { + for (i = 0; i < 2; ++i) + data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_PATCH); + + data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); + data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); + + // get background tile + bgtile = W_CachePatchName("SPECTILE", PU_PATCH); + + // grab an interscreen if appropriate + if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') + interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + break; + } + case int_ctf: + case int_teammatch: + { + if (!rflagico) //prevent a crash if we haven't cached our team graphics yet + { + rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); + bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); + rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); + bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); + } + + data.match.redflag = (intertype == int_ctf) ? rflagico : rmatcico; + data.match.blueflag = (intertype == int_ctf) ? bflagico : bmatcico; + } + /* FALLTHRU */ + case int_match: + case int_race: + case int_comp: + { + if (intertype == int_match || intertype == int_race) + { + // get RESULT header + data.match.result = W_CachePatchName("RESULT", PU_PATCH); + } + + // get background tile + bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); + break; + } + case int_none: + default: + break; + } +} + // // Y_ConsiderScreenBuffer // @@ -347,7 +430,7 @@ void Y_IntermissionDrawer(void) else if (bgtile) V_DrawPatchFill(bgtile); - LUAh_IntermissionHUD(); + LUAh_IntermissionHUD(intertype == int_spec && stagefailed); if (!LUA_HudEnabled(hud_intermissiontally)) goto skiptallydrawer; @@ -388,14 +471,17 @@ void Y_IntermissionDrawer(void) } } - // draw the "got through act" lines and act number - V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1); + if (LUA_HudEnabled(hud_intermissiontitletext)) { - INT32 h = V_LevelNameHeight(data.coop.passed2); - V_DrawLevelTitle(data.coop.passedx2, 49+h+2, 0, data.coop.passed2); + // draw the "got through act" lines and act number + V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1); + { + INT32 h = V_LevelNameHeight(data.coop.passed2); + V_DrawLevelTitle(data.coop.passedx2, 49+h+2, 0, data.coop.passed2); - if (data.coop.actnum) - V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum); + if (data.coop.actnum) + V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum); + } } bonusy = 150; @@ -479,37 +565,44 @@ void Y_IntermissionDrawer(void) if (drawsection == 1) { - const char *ringtext = "\x82" "50 rings, no shield"; - const char *tut1text = "\x82" "press " "\x80" "spin"; - const char *tut2text = "\x82" "mid-" "\x80" "jump"; - ttheight = 8; - V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); - ttheight += V_LevelNameHeight(data.spec.passed3) + 2; - V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); - ttheight += V_LevelNameHeight(data.spec.passed4) + 2; - V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4); + if (LUA_HudEnabled(hud_intermissiontitletext)) + { + const char *ringtext = "\x82" "50 rings, no shield"; + const char *tut1text = "\x82" "press " "\x80" "spin"; + const char *tut2text = "\x82" "mid-" "\x80" "jump"; + ttheight = 8; + V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); + ttheight += V_LevelNameHeight(data.spec.passed3) + 2; + V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); + ttheight += V_LevelNameHeight(data.spec.passed4) + 2; + V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4); - ttheight = 108; - V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext); - ttheight += V_LevelNameHeight(tut1text) + 2; - V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text); - ttheight += V_LevelNameHeight(tut2text) + 2; - V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text); + ttheight = 108; + V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext); + ttheight += V_LevelNameHeight(tut1text) + 2; + V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text); + ttheight += V_LevelNameHeight(tut2text) + 2; + V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text); + } } else { INT32 yoffset = 0; - if (data.spec.passed1[0] != '\0') + + if (LUA_HudEnabled(hud_intermissiontitletext)) { - ttheight = 24; - V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); - ttheight += V_LevelNameHeight(data.spec.passed2) + 2; - V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2); - } - else - { - ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2; - V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); + if (data.spec.passed1[0] != '\0') + { + ttheight = 24; + V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); + ttheight += V_LevelNameHeight(data.spec.passed2) + 2; + V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2); + } + else + { + ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2; + V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); + } } V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatches[0]); @@ -555,6 +648,7 @@ void Y_IntermissionDrawer(void) // draw the emeralds //if (intertic & 1) + if (LUA_HudEnabled(hud_intermissionemeralds)) { boolean drawthistic = !(ALL7EMERALDS(emeralds) && (intertic & 1)); INT32 emeraldx = 152 - 3*28; @@ -927,7 +1021,8 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; - LUAh_IntermissionThinker(); + LUA_HookBool(intertype == int_spec && stagefailed, + HOOK(IntermissionThinker)); intertic++; @@ -1181,10 +1276,9 @@ void Y_DetermineIntermissionType(void) // // Called by G_DoCompleted. Sets up data for intermission drawer/ticker. // +// void Y_StartIntermission(void) { - INT32 i; - intertic = -1; #ifdef PARANOIA @@ -1228,23 +1322,12 @@ void Y_StartIntermission(void) // setup time data data.coop.tics = players[consoleplayer].realtime; - for (i = 0; i < 4; ++i) - { - if (strlen(data.coop.bonuses[i].patch)) - data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_PATCH); - } - data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH); - // get act number data.coop.actnum = mapheaderinfo[gamemap-1]->actnum; - // get background patches - bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); - // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; usebuffer = false; } @@ -1259,24 +1342,40 @@ void Y_StartIntermission(void) usetile = false; // set up the "got through act" message according to skin name - // too long so just show "YOU GOT THROUGH THE ACT" - if (strlen(skins[players[consoleplayer].skin].realname) > 13) + if (stagefailed) { - strcpy(data.coop.passed1, "you got"); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + strcpy(data.coop.passed1, mapheaderinfo[gamemap-1]->lvlttl); + + if (mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) + { + data.spec.passed2[0] = '\0'; + } + else + { + strcpy(data.coop.passed2, "Zone"); + } } - // long enough that "X GOT" won't fit so use "X PASSED THE ACT" - else if (strlen(skins[players[consoleplayer].skin].realname) > 8) - { - strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act"); - } - // length is okay for normal use else { - snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got", - skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + // too long so just show "YOU GOT THROUGH THE ACT" + if (strlen(skins[players[consoleplayer].skin].realname) > 13) + { + strcpy(data.coop.passed1, "you got"); + strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + } + // long enough that "X GOT" won't fit so use "X PASSED THE ACT" + else if (strlen(skins[players[consoleplayer].skin].realname) > 8) + { + strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); + strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act"); + } + // length is okay for normal use + else + { + snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got", + skins[players[consoleplayer].skin].realname); + strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + } } // set X positions @@ -1293,6 +1392,13 @@ void Y_StartIntermission(void) // The above value is not precalculated because it needs only be computed once // at the start of intermission, and precalculating it would preclude mods // changing the font to one of a slightly different width. + + if ((stagefailed) && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + { + // Bit of a hack, offset so that the "Zone" text is right aligned like title cards. + data.coop.passedx2 = (data.coop.passedx1 + V_LevelNameWidth(data.coop.passed1)) - V_LevelNameWidth(data.coop.passed2); + } + break; } @@ -1301,21 +1407,9 @@ void Y_StartIntermission(void) // give out ring bonuses Y_AwardSpecialStageBonus(); - for (i = 0; i < 2; ++i) - data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_PATCH); - - data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); - data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); - - // get background tile - bgtile = W_CachePatchName("SPECTILE", PU_PATCH); - // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') - { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; - } else useinterpic = false; @@ -1408,11 +1502,6 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - // get RESULT header - data.match.result = - W_CachePatchName("RESULT", PU_PATCH); - - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1437,10 +1526,6 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - // get RESULT header - data.match.result = W_CachePatchName("RESULT", PU_PATCH); - - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1466,18 +1551,6 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; - if (intertype == int_ctf) - { - data.match.redflag = rflagico; - data.match.blueflag = bflagico; - } - else // team match - { - data.match.redflag = rmatcico; - data.match.blueflag = bmatcico; - } - - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1502,8 +1575,6 @@ void Y_StartIntermission(void) data.competition.levelstring[sizeof data.competition.levelstring - 1] = '\0'; - // get background tile - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1748,21 +1819,30 @@ static void Y_SetTimeBonus(player_t *player, y_bonus_t *bstruct) strncpy(bstruct->patch, "YB_TIME", sizeof(bstruct->patch)); bstruct->display = true; - // calculate time bonus - secs = player->realtime / TICRATE; - if (secs < 30) /* :30 */ bonus = 50000; - else if (secs < 60) /* 1:00 */ bonus = 10000; - else if (secs < 90) /* 1:30 */ bonus = 5000; - else if (secs < 120) /* 2:00 */ bonus = 4000; - else if (secs < 180) /* 3:00 */ bonus = 3000; - else if (secs < 240) /* 4:00 */ bonus = 2000; - else if (secs < 300) /* 5:00 */ bonus = 1000; - else if (secs < 360) /* 6:00 */ bonus = 500; - else if (secs < 420) /* 7:00 */ bonus = 400; - else if (secs < 480) /* 8:00 */ bonus = 300; - else if (secs < 540) /* 9:00 */ bonus = 200; - else if (secs < 600) /* 10:00 */ bonus = 100; - else /* TIME TAKEN: TOO LONG */ bonus = 0; + if (stagefailed == true) + { + // Time Bonus would be very easy to cheese by failing immediately. + bonus = 0; + } + else + { + // calculate time bonus + secs = player->realtime / TICRATE; + if (secs < 30) /* :30 */ bonus = 50000; + else if (secs < 60) /* 1:00 */ bonus = 10000; + else if (secs < 90) /* 1:30 */ bonus = 5000; + else if (secs < 120) /* 2:00 */ bonus = 4000; + else if (secs < 180) /* 3:00 */ bonus = 3000; + else if (secs < 240) /* 4:00 */ bonus = 2000; + else if (secs < 300) /* 5:00 */ bonus = 1000; + else if (secs < 360) /* 6:00 */ bonus = 500; + else if (secs < 420) /* 7:00 */ bonus = 400; + else if (secs < 480) /* 8:00 */ bonus = 300; + else if (secs < 540) /* 9:00 */ bonus = 200; + else if (secs < 600) /* 10:00 */ bonus = 100; + else /* TIME TAKEN: TOO LONG */ bonus = 0; + } + bstruct->points = bonus; } @@ -1815,12 +1895,21 @@ static void Y_SetGuardBonus(player_t *player, y_bonus_t *bstruct) strncpy(bstruct->patch, "YB_GUARD", sizeof(bstruct->patch)); bstruct->display = true; - if (player->timeshit == 0) bonus = 10000; - else if (player->timeshit == 1) bonus = 5000; - else if (player->timeshit == 2) bonus = 1000; - else if (player->timeshit == 3) bonus = 500; - else if (player->timeshit == 4) bonus = 100; - else bonus = 0; + if (stagefailed == true) + { + // "No-hit" runs would be very easy to cheese by failing immediately. + bonus = 0; + } + else + { + if (player->timeshit == 0) bonus = 10000; + else if (player->timeshit == 1) bonus = 5000; + else if (player->timeshit == 2) bonus = 1000; + else if (player->timeshit == 3) bonus = 500; + else if (player->timeshit == 4) bonus = 100; + else bonus = 0; + } + bstruct->points = bonus; } @@ -2033,7 +2122,8 @@ static void Y_AwardSpecialStageBonus(void) // void Y_EndIntermission(void) { - Y_UnloadData(); + if (!dedicated) + Y_UnloadData(); endtic = -1; intertype = int_none; diff --git a/src/y_inter.h b/src/y_inter.h index 859144b1d..871142858 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2020 by Sonic Team Junior. +// Copyright (C) 2004-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -14,6 +14,7 @@ extern boolean usebuffer; void Y_IntermissionDrawer(void); void Y_Ticker(void); +void Y_LoadIntermissionData(void); void Y_StartIntermission(void); void Y_EndIntermission(void); diff --git a/src/z_zone.c b/src/z_zone.c index d7da17e51..34ff3d37e 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/z_zone.h b/src/z_zone.h index 7b58be8f3..be55bf994 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2.