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.