diff --git a/.gitignore b/.gitignore
index 8b73f04f5..7f8d56035 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,16 +13,17 @@ Win32_LIB_ASM_Release
*.dgb
*.debug
*.debug.txt
-/bin/VC10/
-/objs/VC10/
*.user
*.db
*.opendb
/.vs
/debian
/assets/debian
-compile.sh
-*.gz
-.vscode/
-out
-build
+/make
+/bin
+/build
+/build/*
+/CMakeUserPresets.json
+/out
+/objs/VC10
+*.kate-swp
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 c63fd53bc..000000000
--- a/bin/Linux64/Release/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/lsdl2srb2kart
diff --git a/bin/Mingw/Debug/.gitignore b/bin/Mingw/Debug/.gitignore
deleted file mode 100644
index 3458ff764..000000000
--- a/bin/Mingw/Debug/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-*.exe
-*.mo
-r_opengl.dll
-*.bat
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 b2443f38d..000000000
--- a/bin/Mingw64/Release/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-*.exe
-*.mo
-r_opengl.dll
-*.bat
\ No newline at end of file
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/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/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/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 729b5896a..4ce38953d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -228,6 +228,14 @@ set(SRB2_CONFIG_STATIC_OPENGL OFF CACHE BOOL
"Use statically linked OpenGL. NOT RECOMMENDED.")
set(SRB2_CONFIG_USE_FBO_OGL ON CACHE BOOL
"Enable OpenGL FBO Downsampling support.")
+set(SRB2_CONFIG_DEDICATED OFF CACHE BOOL
+ "Build a dedicated server.")
+
+if(${SRB2_CONFIG_DEDICATED})
+ set(SRB2_CONFIG_HAVE_GME NO)
+ set(SRB2_CONFIG_HAVE_OPENMPT NO)
+ set(SRB2_CONFIG_HWRENDER NO)
+endif()
### use internal libraries?
if(${CMAKE_SYSTEM} MATCHES "Windows") ###set on Windows only
@@ -554,7 +562,11 @@ add_definitions(-DCMAKECONFIG)
# ${SRB2_BLUA_HEADERS}
#)
-add_subdirectory(sdl)
+if(${SRB2_CONFIG_DEDICATED})
+ add_subdirectory(dedicated)
+else()
+ add_subdirectory(sdl)
+endif()
if(NOT ${SRB2_SDL2_AVAILABLE} AND NOT ${SRB2_WIN32_AVAILABLE})
message(FATAL_ERROR "There are no targets available to build an SRB2Kart executable. :(")
diff --git a/src/Makefile b/src/Makefile
index b6077ba6c..9acfd6d3c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,783 +1,430 @@
-
-# GNU Make makefile for SRB2
-#############################################################################
-# Copyright (C) 1998-2000 by DooM Legacy Team.
-# Copyright (C) 2003-2018 by Sonic Team Junior.
+# GNU Makefile for SRB2
+# the poly3 Makefile adapted over and over...
+#
+# Copyright 1998-2000 DooM Legacy Team.
+# Copyright 2020-2023 James R.
+# Copyright 2003-2023 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
-# -DHAVE_SDL -> use for the SDL interface
+# Special targets:
#
-# Sets:
-# Compile the Mingw version with 'make MINGW=1'
-# Compile the SDL/Mingw version with 'make MINGW=1 SDL=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 depend.dep
-# 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
+# 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.
#
#
-# 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 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 BSD API, add 'NONET=1'
-# Compile without IPX/SPX, add 'NOIPX=1'
-# Compile without libopenmpt, add 'NOOPENMPT=1'
-# 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 implemented backend though.
+# If disabled, a dummy backend will be used.
#
-#############################################################################
+# A list of supported GCC versions can be found in
+# Makefile.d/detect.mk -- search 'gcc_versions'.
+#
+# Feature flags:
+#
+# Safe to use online
+# ------------------
+# NOHW=1 - Disable OpenGL renderer.
+# NOSCREENFBO=1 - Disable screen FBO for downsampling in OpenGL.
+# NOSATURNPAK=1 - Disable handling the special Saturn packet and resynch system
+# NOSATURNJOIN=1 - Disable the seperate Saturn allowjoin toggle
+# ZDEBUG=1 - Enable more detailed memory debugging
+# HAVE_MINIUPNPC=1 - Enable automated port forwarding.
+# Already enabled by default for 32-bit
+# Windows.
+# 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).
+# NOTHREADS=1 - Disable multithreading.
+#
+# Netplay incompatible
+# --------------------
+# NOMD5=1 - Disable MD5 checksum (validation tool).
+# NOPOSTPROCESSING=1 - ?
+# MOBJCONSISTANCY=1 - ??
+# PACKETDROP=1 - ??
+# NOEXECINFO=1 - Disable stack trace dump support
+# DEBUGMODE=1 - Enable various debugging capabilities.
+# Also disables optimizations.
+#
+# Development flags:
+#
+# VALGRIND=1 - Enable Valgrind memory debugging support.
+# PROFILEMODE=1 - Enable performance profiling (gprof).
+# USEASAN=1 - Enable building with Address Sanitizer.
+# NOLIBBACKTRACE=1 - Disable using Libbacktrace for crashlog traces.
+#
+# 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.
+# 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 - ?
+# USELTO=1 - Enable building with LTO.
+#
+# 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=
-ALL_SYSTEMS=\
- PANDORA\
- LINUX64\
- MINGW64\
- HAIKU\
- MINGW\
- UNIX\
- LINUX\
- SOLARIS\
- FREEBSD\
- MACOSX\
- SDL\
+# LIBOPENMPT_PKGCONFIG=
+# LIBOPENMPT_CFLAGS=, LIBOPENMPT_LDFLAGS=
+#
+# ZLIB_PKGCONFIG=, ZLIB_CFLAGS=, ZLIB_LDFLAGS=
+#
+# SDL_PKGCONFIG=
+# SDL_CONFIG= - sdl-config command.
+# SDL_CFLAGS=, SDL_LDFLAGS=
-# check for user specified system
-ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES)))
-ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
+clean_targets=cleandep clean distclean info
- ifeq ($(shell uname -s | grep -o MINGW64),MINGW64) # 64-bit MinGW
- $(info Detected a Windows system, compiling for 64-bit MinGW SDL2...)
- MINGW64=1
- else # 32-bit MinGW
- $(info Detected a Windows system, compiling for 32-bit MinGW SDL2...)
- MINGW=1
- endif
+.PHONY : $(clean_targets) all
- SDL=1
- WINDOWSHELL=1
- NOOBJDUMP=1
+goals:=$(or $(MAKECMDGOALS),all)
+cleanonly:=$(filter $(clean_targets),$(goals))
+destructive:=$(filter-out info,$(cleanonly))
-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
-
- $(info Detected $(system) ($(new_system))...)
- $(new_system)=1
-
-endif
+ifndef cleanonly
+include Makefile.d/old.mk
endif
-NOUPX=1
+include Makefile.d/util.mk
-# SRB2 data files
-D_DIR?=../bin/Resources
-D_FILES=$(D_DIR)/srb2.srb \
- $(D_DIR)/patch.dta \
- #$(D_DIR)/music.dta \
- $(D_DIR)/gfx.kart \
- $(D_DIR)/textures.kart \
- $(D_DIR)/chars.kart \
- $(D_DIR)/maps.kart \
- $(D_DIR)/sounds.kart \
- $(D_DIR)/patch.kart \
- $(D_DIR)/music.kart \
-
-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
-# 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 HAIKU
-NOIPX=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
-
-ifndef NOHW
-ifndef NOSCREENFBO
-USE_FBO_OGL=1
-endif
-endif
-
-ifndef NONET
-ifndef NOSATURNJOIN
-DOSATURNJOIN=1
-endif
-ifndef NOSATURNPAK
-DOSATURNPAK=1
-endif
-endif
-
-ifdef MINGW
-include win32/Makefile.cfg
-endif #ifdef MINGW
-
-ifdef UNIX
-UNIXCOMMON=1
-endif
-
-ifdef LINUX
-UNIXCOMMON=1
-NOOBJDUMP=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
-
-ifndef ECHO
- REMOVE:=@$(REMOVE)
- CC:=@$(CC)
- CXX:=@$(CXX)
- OBJCOPY:=@$(OBJCOPY)
- OBJDUMP:=@$(OBJDUMP)
- STRIP:=@$(STRIP)
- WINDRES:=@$(WINDRES)
- CP:=@$(CP)
- MKDIR:=@$(MKDIR)
- MKISOFS:=@$(MKISOFS)
- DD:=@$(DD)
- NDSTOOL:=@$(NDSTOOL)
- GZIP:=@$(GZIP)
- MSGFMT:=@$(MSGFMT)
- UPX:=@$(UPX)
- UPX_OPTS+=-q
-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_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_portal.o\
- $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o $(OBJDIR)/hw_shaders.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
-
-# apparently MingW just completely ignores everything so just always force this shit
-# FIXME: we should port our code to c24
-CFLAGS+=-std=gnu17
-CPPFLAGS+=-std=gnu17
-
-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
+CXX:=$(PREFIX)-g++
+endif
+
+OBJDUMP_OPTS?=--wide --source --line-numbers
+
+OBJCOPY?=$(call Prefix,objcopy)
+OBJDUMP?=$(call Prefix,objdump)
+WINDRES?=$(call Prefix,windres)
+
+GZIP?=gzip
+GZIP_OPTS?=-9 -f -n
+ifdef WINDOWSHELL
+GZIP_OPTS+=--rsyncable
+endif
+
+UPX_OPTS?=--best --preserve-build-id
+ifndef ECHO
+UPX_OPTS+=-qq
+endif
+
+include Makefile.d/detect.mk
+
+# 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:=
+
+# 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)
+
+sources+=\
+ $(call List,blua/Sourcefile)
+
+depends:=$(basename $(filter %.c %.cpp %.s,$(sources)))
+objects:=$(basename $(filter %.c %.cpp %.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
-PNG_CONFIG?=libpng-config
+bin:=../bin
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
+# default EXENAME (usually set by platform)
+EXENAME?=srb2kart
+DBGNAME?=$(EXENAME).debug
-ifdef LINUX
-PNG_CFLAGS+=-D_LARGEFILE64_SOURCE
-endif
+exe:=$(bin)/$(EXENAME)
+dbg:=$(bin)/$(DBGNAME)
-LIBS+=$(PNG_LDFLAGS)
-CFLAGS+=$(PNG_CFLAGS)
+build_done==== Build is done, look for \
+ $( $@
+ $(.)$(GZIP) $(GZIP_OPTS) $@
+
+# '::' means run unconditionally
+# this really updates comptime.h
+comptime.c ::
ifdef WINDOWSHELL
-$(.)..\comptime.bat .
else
-$(.)../comptime.sh .
endif
-clean: cleandep
- $(REMOVE) *~ *.flc
- $(REMOVE) $(OBJDIR)/*.o
+# I wish I could make dependencies out of rc files :(
+$(objdir)/win32/Srb2win.res : \
+ win32/afxres.h win32/resource.h
-ifdef MINGW
- $(REMOVE) $(OBJDIR)/*.res
-endif
-
-ifdef CYGWIN32
- $(REMOVE) $(OBJDIR)/*.res
-endif
-
-
-# executable
-
-$(BIN)/$(EXENAME): $(POS) $(OBJS)
- -$(MKDIR) $(BIN)
- @echo Linking $(EXENAME)...
- $(LD) $(LDFLAGS) $(OBJS) -o $(BIN)/$(EXENAME) $(LIBS)
-ifndef VALGRIND
-ifndef NOOBJDUMP
- @echo Dumping debugging info
- $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt
- -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
+# dependency recipe template
+# 1: source file suffix
+# 2: extra flags to gcc
+define _recipe =
+$(depdir)/%.d : %.$(1) | $$$$(@D)/
ifndef WINDOWSHELL
- -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
+ifdef Echo_name
+ @printf '%-20.20s\r' $$<
endif
endif
+ $(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
+endef
-# 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
-
-ifdef APPIMAGE
- @echo Building AppImage...
-ifdef APPIMAGE_NOASSETS
- $(.)../AppImage_build.sh --small --quiet $(BIN)/
-else
- $(.)../AppImage_build.sh -q $(BIN)/
-endif
- @echo AppImage build complete, please look for $(EXENAME).AppImage in $(BIN)
-endif
-
- @echo Build is done, please look for $(EXENAME) in $(BIN), \(checking for post steps\)
-
-reobjdump:
- @echo Redumping debugging info
- $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt
- -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
+# dependency recipe template (C++)
+# 1: source file suffix
+# 2: extra flags to gcc
+define _recipecxx =
+$(depdir)/%.d : %.$(1) | $$$$(@D)/
ifndef WINDOWSHELL
- -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
+ifdef Echo_name
+ @printf '%-20.20s\r' $$<
endif
+endif
+ $(.)$(cxx) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
+endef
-$(OBJDIR):
- -$(MKDIR) $(OBJDIR)
+$(eval $(call _recipe,c))
+$(eval $(call _recipe,cpp))
+$(eval $(call _recipe,s,$(asflags)))
-ifndef SDL
-ifdef NOHW
-dll :
+# 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
+
+$(eval $(call _recipe,o,c,$(cc) -c -o $$@ $$<))
+$(eval $(call _recipe,o,cpp,$(cxx) -c -o $$@ $$<))
+$(eval $(call _recipe,o,s,$(cc) $(asflags) -c -o $$@ $$<))
+$(eval $(call _recipe,res,rc,$(windres) -i $$< -o $$@))
+
+_rm=$(.)$(rmrf) $(call Windows_path,$(1))
+
+cleandep :
+ $(call _rm,$(depends) comptime.h)
+
+clean :
+ $(call _rm,$(exe) $(dbg) $(dbg).txt $(objects))
+
+distclean :
+ $(call _rm,../bin ../objs ../dep ../make comptime.h)
+
+info:
+ifdef WINDOWSHELL
+ @REM
else
-dll : opengl_dll
-endif
-ifdef MINGW
-all_dll: opengl_dll
-
-opengl_dll: $(BIN)/r_opengl.dll
-$(BIN)/r_opengl.dll: $(OBJDIR)/ogl_win.o $(OBJDIR)/r_opengl.o
- -$(MKDIR) $(BIN)
- @echo Linking R_OpenGL.dll...
- $(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lgdi32 -static-libgcc
-ifndef NOUPX
- -$(UPX) $(UPX_OPTS) $@
-endif
+ @:
endif
-else
-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_gl.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_portal.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
- $(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_gl.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_portal.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
- $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
-endif
-endif
-
-endif
-
-#dependecy made by gcc itself !
-$(OBJS):
--include $(OBJDIR)/depend.dep
-
-$(OBJDIR)/depend.dep:
- @echo "Creating dependency file, depend.dep"
- @echo > comptime.h
- -$(MKDIR) $(OBJDIR)
- $(CC) $(CFLAGS) -MM *.c > $(OBJDIR)/depend.ped
- $(CC) $(CFLAGS) -MM $(INTERFACE)/*.c >> $(OBJDIR)/depend.ped
-ifndef NOHW
- $(CC) $(CFLAGS) -MM hardware/*.c >> $(OBJDIR)/depend.ped
-endif
-
- $(CC) $(CFLAGS) -MM blua/*.c >> $(OBJDIR)/depend.ped
-
- @sed -e 's,\(.*\)\.o: ,$(subst /,\/,$(OBJDIR))\/&,g' < $(OBJDIR)/depend.ped > $(OBJDIR)/depend.dep
- $(REMOVE) $(OBJDIR)/depend.ped
- @echo "Created dependency file, depend.dep"
-
-ifdef VALGRIND
-$(OBJDIR)/z_zone.o: z_zone.c
- $(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@
-endif
-
-$(OBJDIR)/comptime.o: comptime.c pre-build
- $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(BIN)/%.mo: locale/%.po
- -$(MKDIR) $(BIN)
- $(MSGFMT) -f -o $@ $<
-
-$(OBJDIR)/%.o: %.c
- $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(OBJDIR)/%.o: $(INTERFACE)/%.c
- $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-ifdef MACOSX
-$(OBJDIR)/%.o: sdl/macosx/%.c
- $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-endif
-
-$(OBJDIR)/%.o: hardware/%.c
- $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(OBJDIR)/%.o: blua/%.c
- $(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(OBJDIR)/%.o: %.s
- $(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@
-
-$(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h
- $(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff
-
-ifdef SDL
-ifdef MINGW
-$(OBJDIR)/win_dbg.o: win32/win_dbg.c
- $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-endif
-endif
-
-#############################################################
-#
-#############################################################
+#$(warning The handwritten GNU Makefile for SRB2 is deprecated, and may be removed in the future. Please consider switching to CMake.)
diff --git a/src/Makefile.d/dedicated.mk b/src/Makefile.d/dedicated.mk
new file mode 100644
index 000000000..fef452467
--- /dev/null
+++ b/src/Makefile.d/dedicated.mk
@@ -0,0 +1,21 @@
+makedir:=$(makedir)/Dedicated
+
+sources+=$(call List,dedicated/Sourcefile)
+
+opts+=-DDEDICATED
+
+libs+=-lpthread
+
+ifdef MINGW
+libs+=-mconsole
+endif
+
+ifndef NOTHREADS
+opts+=-DHAVE_THREADS
+sources+=dedicated/i_threads.c
+endif
+
+NOOPENMPT=1
+NOGME=1
+NOHW=1
+NOUPNP=1
diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk
new file mode 100644
index 000000000..dd31d2f3e
--- /dev/null
+++ b/src/Makefile.d/detect.mk
@@ -0,0 +1,124 @@
+#
+# Detect the host system and compiler version.
+#
+
+# Previously featured:\
+ PANDORA\
+ DUMMY\
+ DJGPPDOS\
+ SOLARIS\
+ MACOSX\
+
+all_systems:=\
+ LINUX64\
+ MINGW64\
+ MINGW\
+ UNIX\
+ LINUX\
+ FREEBSD\
+ HAIKU\
+
+# check for user specified system
+ifeq (,$(filter $(all_systems),$(.VARIABLES)))
+ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
+
+ ifeq ($(shell uname -s | grep -o MINGW64),MINGW64) # 64-bit MinGW
+ _m=Detected a Windows system,\
+ compiling for 64-bit MinGW SDL...)
+ $(call Print,$(_m))
+ MINGW64=1
+ else # 32-bit MinGW
+ _m=Detected a Windows system,\
+ compiling for 32-bit MinGW SDL...)
+ $(call Print,$(_m))
+ MINGW=1
+ endif
+
+ NOOBJDUMP=1
+else # if you on the *nix
+
+system:=$(shell uname -s)
+
+ifeq ($(system),Linux)
+new_system:=LINUX
+else ifeq ($(system),Haiku)
+new_system:=HAIKU
+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:=\
+ 151 150 15\
+ 142 141 140 14\
+ 132 131 130 13\
+ 123 122 121 120 12\
+ 114 113 112 111 110 11\
+ 105 104 103 102 101 100 10\
+ 95 94 93 92 91 90\
+ 85 84 83 82 81 80\
+ 75 74 73 72 71 70\
+ 64 63 62 61 60\
+ 55 54 53 52 51 50\
+ 49 48 47 46 45 44 43 42 41 40
+
+latest_gcc_version:=15.1.1
+
+# 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))
+
+# can't use $(CC) --version here since that uses argv[0] to display the name
+# also gcc outputs the information to stderr, so I had to do 2>&1
+# this program really doesn't like identifying itself
+shellversion:=$(shell $(CC) -v 2>&1)
+# Try to remove "-win32"
+version:=$(subst -win32,.0,$(shellversion))
+
+# check if this is in fact GCC
+ifneq (,$(findstring gcc version,$(version)))
+
+# in stark contrast to the name, gcc will give me a nicely formatted version number for free
+shellversion:=$(shell $(CC) -dumpfullversion)
+
+# Try to remove "-win32"
+version:=$(subst -win32,.0,$(shellversion))
+
+# 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..ca789dbee
--- /dev/null
+++ b/src/Makefile.d/features.mk
@@ -0,0 +1,106 @@
+#
+# Makefile for feature flags.
+#
+
+passthru_opts+=\
+ NOHW NOMD5 NOPOSTPROCESSING\
+ MOBJCONSISTANCY PACKETDROP ZDEBUG\
+ HAVE_MINIUPNPC\
+ HAVE_DISCORDRPC DEVELOP\
+ NOBLUAJIT
+
+# build with debugging information
+ifdef DEBUGMODE
+PACKETDROP=1
+opts+=-DPARANOIA -DRANGECHECK
+endif
+
+ifndef NOHW
+opts+=-DHWRENDER
+
+ifndef NOSCREENFBO
+opts+=-DUSE_FBO_OGL
+endif
+
+sources+=$(call List,hardware/Sourcefile)
+endif
+
+ifndef NOMD5
+sources+=md5.c
+endif
+
+ifndef NONET
+ifndef NOSATURNJOIN
+opts+=-DDOSATURNJOIN
+endif
+ifndef NOSATURNPAK
+opts+=-DDOSATURNPAK
+endif
+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_LARGEFILE64_SOURCE
+endif
+opts+=-DHAVE_PNG
+sources+=apng.c
+endif
+endif
+
+ifndef NOCURL
+CURLCONFIG?=curl-config
+$(eval $(call Configure,CURL,$(CURLCONFIG)))
+opts+=-DHAVE_CURL
+endif
+
+ifdef HAVE_MINIUPNPC
+MINIUPNPC_PKGCONFIG?=miniupnpc
+$(eval $(call Use_pkg_config,MINIUPNPC))
+HAVE_MINIUPNPC=1
+opts+=-DHAVE_MINIUPNPC
+endif
+
+ifndef NOLIBBACKTRACE
+$(eval $(call Propogate_flags,LIBBACKTRACE))
+libs+=-lbacktrace
+opts+=-DHAVE_LIBBACKTRACE
+endif
+
+#windoze hack
+ifdef MINGW
+ifndef NODISCORDRPC
+HAVE_DISCORDRPC=1
+endif
+endif
+
+ifdef HAVE_DISCORDRPC
+$(eval $(call Propogate_flags,DISCORDRPC))
+libs+=-ldiscord-rpc
+opts+=-DUSE_STUN
+sources+=discord.c stun.c
+endif
+
+# (Valgrind is a memory debugger.)
+ifdef VALGRIND
+VALGRIND_PKGCONFIG?=valgrind
+VALGRIND_LDFLAGS=
+$(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/haiku.mk b/src/Makefile.d/haiku.mk
new file mode 100644
index 000000000..6742ec75b
--- /dev/null
+++ b/src/Makefile.d/haiku.mk
@@ -0,0 +1,71 @@
+#
+# Makefile options for Haiku
+#
+
+opts+=-DUNIXCOMMON -DLUA_USE_POSIX
+
+ifndef DEDICATED
+ifndef DUMMY
+SDL?=1
+DEDICATED?=0
+endif
+endif
+
+NOEXECINFO=1
+
+ifeq (${SDL},1)
+EXENAME?=srb2haiku
+else ifeq (${DEDICATED},1)
+EXENAME?=srb2haikud
+endif
+
+ifndef NONET
+libs+=-lnetwork
+endif
+
+define _set =
+$(1)_CFLAGS?=$($(1)_opts)
+$(1)_LDFLAGS?=$($(1)_libs)
+endef
+
+lib:=../libs/gme
+LIBGME_opts:=-I$(lib)/include
+LIBGME_libs:=-l:libgme.so.0
+$(eval $(call _set,LIBGME))
+
+lib:=../libs/libopenmpt
+LIBOPENMPT_opts:=-I$(lib)/inc
+LIBOPENMPT_libs:=-l:libopenmpt.so.0
+$(eval $(call _set,LIBOPENMPT))
+
+ifdef SDL
+lib:=../libs/SDL2_mixer
+mixer_opts:=-I$(lib)/include
+mixer_libs:=-l:libSDL2_mixer-2.0.so.0
+
+lib:=../libs/SDL2
+SDL_opts:=-I$(lib)/include $(mixer_opts)
+SDL_libs:=$(mixer_libs) -l:libSDL2-2.0.so.0
+$(eval $(call _set,SDL))
+endif
+
+lib:=../libs/zlib
+ZLIB_opts:=-I$(lib)
+ZLIB_libs:=-l:libz.so.1
+$(eval $(call _set,ZLIB))
+
+ifndef PNG_CONFIG
+PNG_opts:=
+PNG_libs:=-l:libpng16.so.16
+$(eval $(call _set,PNG))
+endif
+
+lib:=../libs/curl
+CURL_opts:=-I$(lib)/include
+CURL_libs:=-l:libcurl.so.4
+$(eval $(call _set,CURL))
+
+lib:=../libs/miniupnpc
+MINIUPNPC_opts:=-I$(lib)/include
+MINIUPNPC_libs:=-l:libminiupnpc.so.17
+$(eval $(call _set,MINIUPNPC))
diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk
new file mode 100644
index 000000000..7135f258b
--- /dev/null
+++ b/src/Makefile.d/nix.mk
@@ -0,0 +1,47 @@
+#
+# Makefile options for unices (linux, bsd...)
+#
+
+
+opts+=-DUNIXCOMMON -DLUA_USE_POSIX
+# Use -rdynamic so a backtrace log shows function names
+# instead of addresses
+libs+=-lm -rdynamic
+
+ifndef NOHW
+opts+=-I/usr/X11R6/include
+libs+=-L/usr/X11R6/lib
+endif
+
+ifndef DEDICATED
+SDL?=1
+DEDICATED?=0
+endif
+
+ifeq (${SDL},1)
+EXENAME?=lsdl2srb2kart
+endif
+
+ifeq (${DEDICATED},1)
+EXENAME?=lsrb2kartd
+endif
+
+# 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 -lkvm -lexecinfo
+endif
+
+# FIXME: UNTESTED
+#ifdef SOLARIS
+#NOIPX=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..ec9b6d776
--- /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 ../dep)
+
+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..d5423a397
--- /dev/null
+++ b/src/Makefile.d/platform.mk
@@ -0,0 +1,76 @@
+#
+# 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 HAIKU
+# Give Haiku its own configuration, since it
+# isn't actually UNIX.
+include Makefile.d/haiku.mk
+else ifdef SOLARIS # FIXME: UNTESTED
+UNIX=1
+platform=solaris
+else ifdef CYGWIN32 # FIXME: UNTESTED
+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
+
+ifeq ($(SDL), 1)
+include Makefile.d/sdl.mk
+else ifeq ($(DEDICATED), 1)
+include Makefile.d/dedicated.mk
+else
+include Makefile.d/dummy.mk
+endif
diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk
new file mode 100644
index 000000000..9f2074d9d
--- /dev/null
+++ b/src/Makefile.d/sdl.mk
@@ -0,0 +1,71 @@
+#
+# 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
+
+NOUPNP=1
+
+# 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
+
+ ifndef HAIKU # Haiku has a special import path
+ 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
+
+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..a3cdbbd4b
--- /dev/null
+++ b/src/Makefile.d/versions.mk
@@ -0,0 +1,178 @@
+#
+# 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
+
+ifdef GCC150
+ opts+=-std=gnu17
+endif
+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+=-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 DEBUGMODE
+ WFLAGS+=-Wno-error=inline
+endif
+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-format-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..4946c4ca2
--- /dev/null
+++ b/src/Makefile.d/win32.mk
@@ -0,0 +1,124 @@
+#
+# Mingw, if you don't know, that's Win32/Win64
+#
+
+ifndef MINGW64
+EXENAME?=srb2kart-saturn_32bit.exe
+else
+EXENAME?=srb2kart-saturn_64bit.exe
+endif
+
+# disable dynamicbase if under msys2
+ifdef MSYSTEM
+libs+=-Wl,--disable-dynamicbase
+endif
+
+sources+=win32/Srb2win.rc
+opts+=-DSTDC_HEADERS
+libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32
+
+ifndef DEDICATED
+ifndef DUMMY
+SDL?=1
+endif
+endif
+
+ifndef NOHW
+opts+=-DUSE_WGL_SWAP
+endif
+
+ifdef MINGW64
+libs+=-lws2_32
+else
+#ifndef HAVE_IPV6
+#libs+=-lwsock32
+#else
+libs+=-lws2_32
+#endif
+endif
+
+ifndef MINGW64
+libs+=-Wl,--large-address-aware
+NOLIBBACKTRACE=1
+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))
+
+lib:=../libs/SDL2_mixer/$(mingw)
+
+ifdef SDL
+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))
+endif
+
+ifdef MINGW64
+lib:=../libs/libbacktrace
+LIBBACKTRACE_opts:=-I$(lib)/include
+LIBBACKTRACE_libs:=-L$(lib)/lib/x86_64 -lbacktrace
+$(eval $(call _set,LIBBACKTRACE))
+else
+lib:=../libs/drmingw
+opts+=-I$(lib)/include
+libs+=-L$(lib)/lib/win32 -lmgwhelp -lexchndl
+endif
+
+lib:=../libs/zlib
+ZLIB_opts:=-I$(lib)
+ZLIB_libs:=-L$(lib)/win32 -l:libz$(32).a
+$(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))
+
+ifndef MINGW64 # miniupnc is broken with MINGW64
+lib:=../libs/miniupnpc
+MINIUPNPC_opts:=-I$(lib)/include -DMINIUPNP_STATICLIB
+MINIUPNPC_libs:=-L$(lib)/mingw$(32) -lminiupnpc -lws2_32 -liphlpapi
+$(eval $(call _set,MINIUPNPC))
+endif
+
+lib:=../libs/discord-rpc/win$(32)-dynamic
+DISCORDRPC_opts+=-I$(lib)/include
+DISCORDRPC_libs+=-L$(lib)/lib -ldiscord-rpc
+$(eval $(call _set,DISCORDRPC))
diff --git a/src/Sourcefile b/src/Sourcefile
new file mode 100644
index 000000000..227e6c95a
--- /dev/null
+++ b/src/Sourcefile
@@ -0,0 +1,96 @@
+am_map.c
+b_bot.c
+command.c
+console.c
+d_clisrv.c
+d_main.c
+d_net.c
+d_netcmd.c
+d_netfil.c
+d_protocol.c
+dehacked.c
+f_finale.c
+f_wipe.c
+filesrch.c
+g_game.c
+g_input.c
+hu_stuff.c
+i_tcp.c
+i_time.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_textinput.c
+m_misc.c
+m_perfstats.c
+m_queue.c
+m_random.c
+mserv.c
+http-mserv.c
+qs22j.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
+r_bsp.c
+r_data.c
+r_draw.c
+r_fps.c
+r_main.c
+r_patch.c
+r_patchrotation.c
+r_plane.c
+r_segs.c
+r_sky.c
+r_splats.c
+r_things.c
+r_portal.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_slopes.c
+p_spec.c
+p_telept.c
+p_tick.c
+p_user.c
+k_director.c
+k_kart.c
+k_stats.c
+lua_baselib.c
+lua_blockmaplib.c
+lua_consolelib.c
+lua_hooklib.c
+lua_hudlib.c
+lua_hudlib_drawlist.c
+lua_infolib.c
+lua_maplib.c
+lua_mathlib.c
+lua_mobjlib.c
+lua_playerlib.c
+lua_script.c
+lua_skinlib.c
+lua_thinkerlib.c
+lua_udatalib.c
+lua_glib.c
diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg
deleted file mode 100644
index f3d38fb70..000000000
--- a/src/blua/Makefile.cfg
+++ /dev/null
@@ -1,55 +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)/ldblib.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_blockmaplib.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_hudlib.o \
- $(OBJDIR)/lua_hudlib_drawlist.o \
- $(OBJDIR)/lua_udatalib.o \
- $(OBJDIR)/lua_glib.o
diff --git a/src/blua/Sourcefile b/src/blua/Sourcefile
new file mode 100644
index 000000000..da89f45a4
--- /dev/null
+++ b/src/blua/Sourcefile
@@ -0,0 +1,26 @@
+lapi.c
+lauxlib.c
+lbaselib.c
+ldblib.c
+lcode.c
+ldebug.c
+ldo.c
+ldump.c
+lfunc.c
+lgc.c
+linit.c
+liolib.c
+llex.c
+lmem.c
+lobject.c
+lopcodes.c
+lparser.c
+lstate.c
+lstring.c
+lstrlib.c
+ltable.c
+ltablib.c
+ltm.c
+lundump.c
+lvm.c
+lzio.c
diff --git a/src/d_main.c b/src/d_main.c
index 728a1a760..79e06285e 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1607,7 +1607,9 @@ void D_SRB2Main(void)
#endif
// for dedicated server
+#if !defined (DEDICATED)
dedicated = M_CheckParm("-dedicated") != 0;
+#endif
strcpy(title, "SRB2Kart");
strcpy(srb2, "SRB2Kart");
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 5b8a8c18b..cf72835db 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -305,14 +305,12 @@ consvar_t cv_verticallook[MAXSPLITSCREENPLAYERS] = {
{"verticallook4", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}
};
-#if defined(HAVE_SDL) || defined(_WINDOWS) //joystick 1 and 2
consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS] = {
{"use_joystick", "1", CV_SAVE|CV_CALL, NULL, I_InitJoystick1, 0, NULL, NULL, 0, 0, NULL},
{"use_joystick2", "2", CV_SAVE|CV_CALL, NULL, I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL},
{"use_joystick3", "3", CV_SAVE|CV_CALL, NULL, I_InitJoystick3, 0, NULL, NULL, 0, 0, NULL},
{"use_joystick4", "4", CV_SAVE|CV_CALL, NULL, I_InitJoystick4, 0, NULL, NULL, 0, 0, NULL}
};
-#endif
#if defined (HAVE_SDL)
consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = {
diff --git a/src/dedicated/CMakeLists.txt b/src/dedicated/CMakeLists.txt
new file mode 100644
index 000000000..36f670251
--- /dev/null
+++ b/src/dedicated/CMakeLists.txt
@@ -0,0 +1,108 @@
+# Declare dedicated interface sources
+
+target_sourcefile(c)
+
+target_sources(SRB2SDL2 PRIVATE)
+
+if(${CMAKE_SYSTEM} MATCHES Windows)
+ target_sources(SRB2SDL2 PRIVATE
+ ../win32/win_dbg.c
+ ../win32/Srb2win.rc)
+endif()
+
+if(${CMAKE_SYSTEM} MATCHES Windows)
+ set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2legacy)
+elseif(${CMAKE_SYSTEM} MATCHES Linux)
+ set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME lsrb2dlegacy)
+else()
+ set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2legacy)
+endif()
+
+if(${CMAKE_SYSTEM} MATCHES Darwin)
+ find_library(CORE_LIB CoreFoundation)
+ target_link_libraries(SRB2SDL2 PRIVATE
+ ${CORE_LIB}
+ ${PNG_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ )
+ set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
+else()
+ target_link_libraries(SRB2SDL2 PRIVATE
+ ${PNG_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ )
+
+ if(${CMAKE_SYSTEM} MATCHES Linux)
+ target_link_libraries(SRB2SDL2 PRIVATE
+ m
+ rt
+ )
+ endif()
+endif()
+
+#target_link_libraries(SRB2SDL2 PRIVATE SRB2Core)
+
+set_target_properties(SRB2SDL2 PROPERTIES VERSION ${SRB2_VERSION})
+
+if(${CMAKE_SYSTEM} MATCHES Windows)
+ target_link_libraries(SRB2SDL2 PRIVATE
+ ws2_32
+ )
+ target_compile_options(SRB2SDL2 PRIVATE
+ -U_WINDOWS
+ )
+endif()
+
+target_include_directories(SRB2SDL2 PRIVATE
+ ${PNG_INCLUDE_DIRS}
+ ${ZLIB_INCLUDE_DIRS}
+)
+
+target_compile_definitions(SRB2SDL2 PRIVATE
+ -DDEDICATED
+)
+
+## strip debug symbols into separate file when using gcc
+if(CMAKE_COMPILER_IS_GNUCC)
+ if(${CMAKE_BUILD_TYPE} MATCHES Debug)
+ message(STATUS "Will make separate debug symbols in *.debug")
+ add_custom_command(TARGET SRB2SDL2 POST_BUILD
+ COMMAND ${OBJCOPY} --only-keep-debug $ $.debug
+ COMMAND ${OBJCOPY} --strip-debug $
+ COMMAND ${OBJCOPY} --add-gnu-debuglink=$.debug $
+ )
+ endif()
+endif()
+
+#### Installation ####
+if(${CMAKE_SYSTEM} MATCHES Darwin)
+ install(TARGETS SRB2SDL2
+ BUNDLE DESTINATION .
+ )
+else()
+ install(TARGETS SRB2SDL2 SRB2SDL2
+ RUNTIME DESTINATION .
+ )
+endif()
+
+# Mac bundle fixup
+# HACK: THIS IS IMPORTANT! See the escaped \${CMAKE_INSTALL_PREFIX}? This
+# makes it so that var is evaluated LATER during cpack, not right now!
+# This fixes the quirk where the bundled libraries don't land in the final package
+# https://cmake.org/pipermail/cmake/2011-March/043532.html
+#
+# HOWEVER: ${CPACK_PACKAGE_DESCRIPTION_SUMMARY} is NOT escaped, because that var
+# is only available to us at this step. Read the link: ${CMAKE_INSTALL_PREFIX} at
+# this current step points to the CMAKE build folder, NOT the folder that CPACK uses.
+# Therefore, it makes sense to escape that var, but not the other.
+if(${CMAKE_SYSTEM} MATCHES Darwin)
+ install(CODE "
+ include(BundleUtilities)
+ fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${CPACK_PACKAGE_DESCRIPTION_SUMMARY}.app\"
+ \"\"
+ /Library/Frameworks
+ )"
+ )
+endif()
+
+set(SRB2_SDL2_AVAILABLE YES PARENT_SCOPE)
diff --git a/src/dedicated/Sourcefile b/src/dedicated/Sourcefile
new file mode 100644
index 000000000..176e60a96
--- /dev/null
+++ b/src/dedicated/Sourcefile
@@ -0,0 +1,7 @@
+i_system.c
+i_main.c
+i_video.c
+i_sound.c
+i_threads.c
+dosstr.c
+endtxt.c
diff --git a/src/dedicated/dosstr.c b/src/dedicated/dosstr.c
new file mode 100644
index 000000000..f9bbee9b4
--- /dev/null
+++ b/src/dedicated/dosstr.c
@@ -0,0 +1,38 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// This file is in the public domain.
+// (Re)written by Graue in 2006.
+//
+//-----------------------------------------------------------------------------
+/// \file
+/// \brief String uppercasing/lowercasing functions for non-DOS non-Win32
+/// systems
+
+#include "../doomtype.h"
+
+#ifndef HAVE_DOSSTR_FUNCS
+
+#include
+
+int strupr(char *n)
+{
+ while (*n != '\0')
+ {
+ *n = toupper(*n);
+ n++;
+ }
+ return 1;
+}
+
+int strlwr(char *n)
+{
+ while (*n != '\0')
+ {
+ *n = tolower(*n);
+ n++;
+ }
+ return 1;
+}
+
+#endif
diff --git a/src/dedicated/endtxt.c b/src/dedicated/endtxt.c
new file mode 100644
index 000000000..1e72ca9a8
--- /dev/null
+++ b/src/dedicated/endtxt.c
@@ -0,0 +1,234 @@
+/*
+ * Function to write the SRB2 end message text
+ *
+ * Copyright (C) 1998 by Udo Munk
+ *
+ * This code is provided AS IS and there are no guarantees, none.
+ * Feel free to share and modify.
+ */
+//-----------------------------------------------------------------------------
+/// \file
+/// \brief Support to show ENDOOM text
+///
+/// Loads the lump ENDOOM, set up the console to print
+/// out the colors and text
+
+#include
+#include
+
+// need this 19990118 by Kin
+#include "../doomdef.h"
+#include "../w_wad.h"
+#include "../z_zone.h"
+#include "endtxt.h"
+/** \brief The ShowEndTxt function
+
+
+ Prints out the ENDOOM the way DOOM.EXE/DOOM2.EXE did for Win32 or Linux/GNU
+
+ \return void
+
+
+*/
+
+void ShowEndTxt(void)
+{
+ INT32 i;
+ UINT16 j, att = 0;
+ INT32 nlflag = 1;
+#ifdef _WIN32
+ HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD mode, bytesWritten;
+ CONSOLE_SCREEN_BUFFER_INFO backupcon;
+ COORD resizewin = {80,-1};
+ CHAR let = 0;
+#endif
+ UINT16 *ptext;
+ void *data;
+ lumpnum_t endoomnum = W_GetNumForName("ENDOOM");
+ //char *col;
+
+ /* if the xterm has more then 80 columns we need to add nl's */
+ /* doesn't work, COLUMNS is not in the environment at this time ???
+ col = I_getenv("COLUMNS");
+ if (col) {
+ if (atoi(col) > 80)
+ nlflag++;
+ }
+ */
+
+ /* get the lump with the text */
+ data = ptext = W_CacheLumpNum(endoomnum, PU_CACHE);
+
+#ifdef _WIN32
+ if (co == INVALID_HANDLE_VALUE || GetFileType(co) != FILE_TYPE_CHAR || !GetConsoleMode(co, &mode)) // test if it a good handle
+ {
+ Z_Free(data);
+ return;
+ }
+
+ backupcon.wAttributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE; // Just in case
+ GetConsoleScreenBufferInfo(co, &backupcon); //Store old state
+ resizewin.Y = backupcon.dwSize.Y;
+ if (backupcon.dwSize.X < resizewin.X)
+ SetConsoleScreenBufferSize(co, resizewin);
+
+ for (i=1; i<=80*25; i++) // print 80x25 text and deal with the attributes too
+ {
+ j = (UINT16)(*ptext >> 8); // attribute first
+ let = (char)(*ptext & 0xff); // text second
+ if (j != att) // attribute changed?
+ {
+ att = j; // save current attribute
+ SetConsoleTextAttribute(co, j); //set fg and bg color for buffer
+ }
+
+ WriteConsoleA(co, &let, 1, &bytesWritten, NULL); // now the text
+
+ if (nlflag && !(i % 80) && backupcon.dwSize.X > resizewin.X) // do we need a nl?
+ {
+ att = backupcon.wAttributes;
+ SetConsoleTextAttribute(co, att); // all attributes off
+ WriteConsoleA(co, "\n", 1, &bytesWritten, NULL); // newline to console
+ }
+ ptext++;
+ }
+ SetConsoleTextAttribute(co, backupcon.wAttributes); // all attributes off
+#else
+ /* print 80x25 text and deal with the attributes too */
+ for (i=1; i<=80*25; i++) {
+ /* attribute first */
+ /* attribute changed? */
+ if ((j = *ptext >> 8) != att) {
+ /* save current attribute */
+ att = j;
+ /* set new attribute, forground color first */
+ printf("\033[");
+ switch (j & 0x0f) {
+ case 0: /* black */
+ printf("30");
+ break;
+ case 1: /* blue */
+ printf("34");
+ break;
+ case 2: /* green */
+ printf("32");
+ break;
+ case 3: /* cyan */
+ printf("36");
+ break;
+ case 4: /* red */
+ printf("31");
+ break;
+ case 5: /* magenta */
+ printf("35");
+ break;
+ case 6: /* brown */
+ printf("33");
+ break;
+ case 7: /* bright grey */
+ printf("37");
+ break;
+ case 8: /* dark grey */
+ printf("1;30");
+ break;
+ case 9: /* bright blue */
+ printf("1;34");
+ break;
+ case 10: /* bright green */
+ printf("1;32");
+ break;
+ case 11: /* bright cyan */
+ printf("1;36");
+ break;
+ case 12: /* bright red */
+ printf("1;31");
+ break;
+ case 13: /* bright magenta */
+ printf("1;35");
+ break;
+ case 14: /* yellow */
+ printf("1;33");
+ break;
+ case 15: /* white */
+ printf("1;37");
+ break;
+ }
+ printf("m");
+ /* now background color */
+ printf("\033[");
+ switch ((j >> 4) & 0x0f) {
+ case 0: /* black */
+ printf("40");
+ break;
+ case 1: /* blue */
+ printf("44");
+ break;
+ case 2: /* green */
+ printf("42");
+ break;
+ case 3: /* cyan */
+ printf("46");
+ break;
+ case 4: /* red */
+ printf("41");
+ break;
+ case 5: /* magenta */
+ printf("45");
+ break;
+ case 6: /* brown */
+ printf("43");
+ break;
+ case 7: /* bright grey */
+ printf("47");
+ break;
+ case 8: /* dark grey */
+ printf("1;40");
+ break;
+ case 9: /* bright blue */
+ printf("1;44");
+ break;
+ case 10: /* bright green */
+ printf("1;42");
+ break;
+ case 11: /* bright cyan */
+ printf("1;46");
+ break;
+ case 12: /* bright red */
+ printf("1;41");
+ break;
+ case 13: /* bright magenta */
+ printf("1;45");
+ break;
+ case 14: /* yellow */
+ printf("1;43");
+ break;
+ case 15: /* white */
+ printf("1;47");
+ break;
+ }
+ printf("m");
+ }
+
+ /* now the text */
+ printf("%c",*ptext++ & 0xff);
+
+ /* do we need a nl? */
+ if (nlflag)
+ {
+ if (!(i % 80))
+ {
+ printf("\033[0m");
+ att = 0;
+ printf("\n");
+ }
+ }
+ }
+ /* all attributes off */
+ printf("\033[0m");
+#endif
+ if (nlflag)
+ printf("\n");
+
+ Z_Free(data);
+}
diff --git a/src/dedicated/endtxt.h b/src/dedicated/endtxt.h
new file mode 100644
index 000000000..41f8e51ad
--- /dev/null
+++ b/src/dedicated/endtxt.h
@@ -0,0 +1,24 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 1998-2000 by DooM Legacy Team.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//-----------------------------------------------------------------------------
+/// \file
+/// \brief Support to show ENDOOM text
+
+#ifndef __ENDTXT__
+#define __ENDTXT__
+
+void ShowEndTxt (void);
+
+#endif
diff --git a/src/dedicated/i_main.c b/src/dedicated/i_main.c
new file mode 100644
index 000000000..911e356d0
--- /dev/null
+++ b/src/dedicated/i_main.c
@@ -0,0 +1,238 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 1993-1996 by id Software, Inc.
+// Copyright (C) 1998-2000 by DooM Legacy Team.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//-----------------------------------------------------------------------------
+/// \file
+/// \brief Main program, simply calls D_SRB2Main and D_SRB2Loop, the high level loop.
+
+#include "../doomdef.h"
+#include "../m_argv.h"
+#include "../d_main.h"
+#include "../m_misc.h" /* path shit */
+#include "../i_system.h"
+#include "../d_clisrv.h"
+
+#if defined (__GNUC__) || defined (__unix__)
+#include
+#endif
+
+#ifdef __unix__
+#include
+#endif
+
+#include "time.h" // For log timestamps
+
+#ifdef HAVE_TTF
+#include "i_ttf.h"
+#endif
+
+#ifdef HAVE_LIBBACKTRACE
+#include
+
+struct backtrace_state *bt_state = NULL;
+#endif
+
+#ifdef LOGMESSAGES
+FILE *logstream = NULL;
+char logfilename[1024];
+#endif
+
+#ifndef DOXYGEN
+#ifndef O_TEXT
+#define O_TEXT 0
+#endif
+
+#ifndef O_SEQUENTIAL
+#define O_SEQUENTIAL 0
+#endif
+#endif
+
+#ifdef _WIN32
+#ifndef _AMD64_
+#include "exchndl.h"
+#define DRMINGW
+#endif
+#endif
+
+#if defined (_WIN32)
+#include "../win32/win_dbg.h"
+typedef BOOL (WINAPI *p_IsDebuggerPresent)(VOID);
+#endif
+
+#ifdef _WIN32
+static void
+ChDirToExe (void)
+{
+ CHAR path[MAX_PATH];
+ if (GetModuleFileNameA(NULL, path, MAX_PATH) > 0)
+ {
+ strrchr(path, '\\')[0] = '\0';
+ SetCurrentDirectoryA(path);
+ }
+}
+#endif
+
+/** \brief The main function
+
+ \param argc number of arg
+ \param *argv string table
+
+ \return int
+*/
+#if defined (__GNUC__) && (__GNUC__ >= 4)
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+#ifdef LOGMESSAGES
+static void InitLogging(void)
+{
+ const char *logdir = NULL;
+ time_t my_time;
+ struct tm * timeinfo;
+ const char *format;
+ const char *reldir;
+ int left;
+ boolean fileabs;
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
+ const char *link;
+#endif
+
+ logdir = D_Home();
+
+ my_time = time(NULL);
+ timeinfo = localtime(&my_time);
+
+ if (M_CheckParm("-logfile") && M_IsNextParm())
+ {
+ format = M_GetNextParm();
+ fileabs = M_IsPathAbsolute(format);
+ }
+ else
+ {
+ format = "log-%Y-%m-%d_%H-%M-%S.txt";
+ fileabs = false;
+ }
+
+ if (fileabs)
+ {
+ strftime(logfilename, sizeof logfilename, format, timeinfo);
+ }
+ else
+ {
+ if (M_CheckParm("-logdir") && M_IsNextParm())
+ reldir = M_GetNextParm();
+ else
+ reldir = "logs";
+
+ if (M_IsPathAbsolute(reldir))
+ {
+ left = snprintf(logfilename, sizeof logfilename,
+ "%s"PATHSEP, reldir);
+ }
+ else
+#ifdef DEFAULTDIR
+ if (logdir)
+ {
+ left = snprintf(logfilename, sizeof logfilename,
+ "%s"PATHSEP DEFAULTDIR PATHSEP"%s"PATHSEP, logdir, reldir);
+ }
+ else
+#endif/*DEFAULTDIR*/
+ {
+ left = snprintf(logfilename, sizeof logfilename,
+ "."PATHSEP"%s"PATHSEP, reldir);
+ }
+
+ strftime(&logfilename[left], sizeof logfilename - left,
+ format, timeinfo);
+ }
+
+ M_MkdirEachUntil(logfilename,
+ M_PathParts(logdir) - 1,
+ M_PathParts(logfilename) - 1, 0755);
+
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
+ logstream = fopen(logfilename, "w");
+#ifdef DEFAULTDIR
+ if (logdir)
+ link = va("%s/"DEFAULTDIR"/latest-log.txt", logdir);
+ else
+#endif/*DEFAULTDIR*/
+ link = "latest-log.txt";
+ unlink(link);
+ if (symlink(logfilename, link) == -1)
+ {
+ I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno));
+ }
+#else/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
+ logstream = fopen("latest-log.txt", "wt+");
+#endif/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ myargc = argc;
+ myargv = argv; /// \todo pull out path to exe from this string
+
+ dedicated = true;
+
+#ifdef HAVE_LIBBACKTRACE
+ bt_state = backtrace_create_state(
+ argv[0],
+#ifdef HAVE_THREADS
+ 1,
+#else
+ 0,
+#endif
+ NULL,
+ NULL
+ );
+#endif
+
+#ifdef _WIN32
+ ChDirToExe();
+#endif
+
+#ifdef LOGMESSAGES
+ if (!M_CheckParm("-nolog"))
+ InitLogging();
+#endif/*LOGMESSAGES*/
+
+ //I_OutputMsg("I_StartupSystem() ...\n");
+ I_StartupSystem();
+#if defined (_WIN32)
+ {
+#ifdef DRMINGW
+ ExcHndlInit();
+#endif
+ }
+#endif
+
+ // startup SRB2
+ CONS_Printf("Setting up SRB2Kart...\n");
+ D_SRB2Main();
+ CONS_Printf("Entering main game loop...\n");
+ // never return
+ D_SRB2Loop();
+
+#ifdef BUGTRAP
+ // This is safe even if BT didn't start.
+ ShutdownBugTrap();
+#endif
+
+ // return to OS
+ return 0;
+}
diff --git a/src/dedicated/i_sound.c b/src/dedicated/i_sound.c
new file mode 100644
index 000000000..de43aab85
--- /dev/null
+++ b/src/dedicated/i_sound.c
@@ -0,0 +1,339 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 1993-1996 by id Software, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// The source is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//-----------------------------------------------------------------------------
+/// \file
+/// \brief SDL interface for sound
+
+#include
+#include "../doomdef.h"
+#include "../i_sound.h"
+#include "../s_sound.h"
+
+/** \brief Sound subsystem runing and waiting
+*/
+UINT8 sound_started = false;
+
+/** \brief The I_GetSfx function
+
+ \param sfx sfx to setup
+
+ \return data for sfx
+*/
+void *I_GetSfx(sfxinfo_t *sfx)
+{
+ (void)sfx;
+ return NULL;
+}
+
+/** \brief The I_FreeSfx function
+
+ \param sfx sfx to be freed up
+
+ \return void
+*/
+void I_FreeSfx(sfxinfo_t *sfx)
+{
+ (void)sfx;
+}
+
+/** \brief Init at program start...
+*/
+void I_StartupSound(void){}
+
+/** \brief ... shut down and relase at program termination.
+*/
+void I_ShutdownSound(void){}
+
+/// ------------------------
+/// SFX I/O
+/// ------------------------
+
+/** \brief Starts a sound in a particular sound channel.
+ \param id sfxid
+ \param vol volume for sound
+ \param sep left-right balancle
+ \param pitch not used
+ \param priority not used
+
+ \return sfx handle
+*/
+INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel)
+{
+ (void)id;
+ (void)vol;
+ (void)sep;
+ (void)pitch;
+ (void)priority;
+ (void)channel;
+ return 0;
+}
+
+/** \brief Stops a sound channel.
+
+ \param handle stop sfx handle
+
+ \return void
+*/
+void I_StopSound(INT32 handle)
+{
+ (void)handle;
+}
+
+/** \brief Some digital sound drivers need this.
+*/
+void I_UpdateSound(void){}
+
+/** \brief Called by S_*() functions to see if a channel is still playing.
+
+ \param handle sfx handle
+
+ \return 0 if no longer playing, 1 if playing.
+*/
+boolean I_SoundIsPlaying(INT32 handle)
+{
+ (void)handle;
+ return false;
+}
+
+/** \brief Updates the sfx handle
+
+ \param handle sfx handle
+ \param vol volume
+ \param sep separation
+ \param pitch ptich
+
+ \return void
+*/
+void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch)
+{
+ (void)handle;
+ (void)vol;
+ (void)sep;
+ (void)pitch;
+}
+
+/** \brief The I_SetSfxVolume function
+
+ \param volume volume to set at
+
+ \return void
+*/
+void I_SetSfxVolume(UINT8 volume)
+{
+ (void)volume;
+}
+
+/// ------------------------
+// MUSIC SYSTEM
+/// ------------------------
+
+/** \brief Init the music systems
+*/
+void I_InitMusic(void){}
+
+/** \brief Shutdown the music systems
+*/
+void I_ShutdownMusic(void){}
+
+/// ------------------------
+// MUSIC PROPERTIES
+/// ------------------------
+
+musictype_t I_SongType(void)
+{
+ return MU_NONE;
+}
+
+boolean I_SongPlaying(void)
+{
+ return false;
+}
+
+boolean I_SongPaused(void)
+{
+ return false;
+}
+
+/// ------------------------
+// MUSIC EFFECTS
+/// ------------------------
+
+boolean I_SetSongSpeed(float speed)
+{
+ (void)speed;
+ return false;
+}
+
+/// ------------------------
+// MUSIC SEEKING
+/// ------------------------
+
+UINT32 I_GetSongLength(void)
+{
+ return 0;
+}
+
+boolean I_SetSongLoopPoint(UINT32 looppoint)
+{
+ (void)looppoint;
+ return false;
+}
+
+UINT32 I_GetSongLoopPoint(void)
+{
+ return 0;
+}
+
+boolean I_SetSongPosition(UINT32 position)
+{
+ (void)position;
+ return false;
+}
+
+UINT32 I_GetSongPosition(void)
+{
+ return 0;
+}
+
+/// ------------------------
+// MUSIC PLAYBACK
+/// ------------------------
+
+/** \brief Registers a song handle to song data.
+
+ \param data pointer to song data
+ \param len len of data
+
+ \return song handle
+
+ \todo Remove this
+*/
+boolean I_LoadSong(char *data, size_t len)
+{
+ (void)data;
+ (void)len;
+ return false;
+}
+
+/** \brief See ::I_LoadSong, then think backwards
+
+ \param handle song handle
+
+ \sa I_LoadSong
+ \todo remove midi handle
+*/
+void I_UnloadSong(void){}
+
+/** \brief Called by anything that wishes to start music
+
+ \param handle Song handle
+ \param looping looping it if true
+
+ \return if true, it's playing the song
+
+ \todo pass music name, not handle
+*/
+boolean I_PlaySong(boolean looping)
+{
+ (void)looping;
+ return false;
+}
+
+/** \brief Stops a song over 3 seconds
+
+ \param handle Song handle
+ \return void
+
+ /todo drop handle
+*/
+void I_StopSong(void){}
+
+/** \brief PAUSE game handling.
+
+ \param handle song handle
+
+ \return void
+*/
+void I_PauseSong(void){}
+
+/** \brief RESUME game handling
+
+ \param handle song handle
+
+ \return void
+*/
+void I_ResumeSong(void){}
+
+/** \brief The I_SetMusicVolume function
+
+ \param volume volume to set at
+
+ \return void
+*/
+void I_SetMusicVolume(UINT8 volume)
+{
+ (void)volume;
+}
+
+boolean I_SetSongTrack(INT32 track)
+{
+ (void)track;
+ return false;
+}
+
+/// ------------------------
+/// MUSIC FADING
+/// ------------------------
+
+void I_SetInternalMusicVolume(UINT8 volume)
+{
+ (void)volume;
+}
+
+void I_StopFadingSong(void){}
+
+boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
+{
+ (void)target_volume;
+ (void)source_volume;
+ (void)ms;
+ (void)callback;
+ return false;
+}
+
+boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
+{
+ (void)target_volume;
+ (void)ms;
+ (void)callback;
+ return false;
+}
+
+boolean I_FadeOutStopSong(UINT32 ms)
+{
+ (void)ms;
+ return false;
+}
+
+boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
+{
+ (void)ms;
+ (void)looping;
+ return false;
+}
+
+void I_UpdateSongLagThreshold(void)
+{
+}
diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c
new file mode 100644
index 000000000..6ab748f86
--- /dev/null
+++ b/src/dedicated/i_system.c
@@ -0,0 +1,2223 @@
+// Emacs style mode select -*- C++ -*-
+//
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 1993-1996 by id Software, Inc.
+// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
+// Copyright (C) 2014-2018 by Sonic Team Junior.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// Changes by Graue are in the public domain.
+//
+//-----------------------------------------------------------------------------
+/// \file
+/// \brief SRB2 system stuff for dedicated
+
+#ifdef CMAKECONFIG
+#include "config.h"
+#else
+#include "../config.h.in"
+#endif
+
+#include
+
+// A little more than the minimum sleep duration on Windows.
+// May be incorrect for other platforms, but we don't currently have a way to
+// query the scheduler granularity. SDL will do what's needed to make this as
+// low as possible though.
+#define MIN_SLEEP_DURATION_MS 2.1
+
+#ifdef _WIN32
+#define RPC_NO_WINDOWS_H
+#include
+#include "../doomtype.h"
+typedef BOOL (WINAPI *p_GetDiskFreeSpaceExA)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
+typedef BOOL (WINAPI *p_IsProcessorFeaturePresent) (DWORD);
+typedef DWORD (WINAPI *p_timeGetTime) (void);
+typedef UINT (WINAPI *p_timeEndPeriod) (UINT);
+typedef HANDLE (WINAPI *p_OpenFileMappingA) (DWORD, BOOL, LPCSTR);
+typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
+#endif
+
+#include
+#include
+#include
+#ifdef __GNUC__
+#include
+#elif defined (_MSC_VER)
+#include
+#endif
+#if defined (__unix__) || defined (UNIXCOMMON)
+#include
+#endif
+
+#include
+#ifdef _WIN32
+#include
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4214 4244)
+#endif
+
+#if defined (__unix__) || defined(__APPLE__) || (defined (UNIXCOMMON) && !defined (__HAIKU__))
+#include
+#if defined (__linux__)
+#include
+#else
+#include
+#include
+/*For meminfo*/
+#include
+#ifdef FREEBSD
+#include
+#endif
+#include
+#include
+#endif
+#endif
+
+#if defined (__linux__) || (defined (UNIXCOMMON) && !defined (__HAIKU__))
+#ifndef NOTERMIOS
+#include
+#include // ioctl
+#define HAVE_TERMIOS
+#endif
+#endif
+
+#if defined (__unix__) || (defined (UNIXCOMMON) && !defined (__APPLE__))
+#include
+#include
+#include
+#define NEWSIGNALHANDLER
+#endif
+
+#ifndef NOMUMBLE
+#ifdef __linux__ // need -lrt
+#include
+#ifdef MAP_FAILED
+#define HAVE_SHM
+#endif
+#include
+#endif
+
+#ifdef _WIN32
+#define HAVE_MUMBLE
+#define WINMUMBLE
+#elif defined (HAVE_SHM)
+#define HAVE_MUMBLE
+#endif
+#endif // NOMUMBLE
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef __APPLE__
+#include "macosx/mac_resources.h"
+#endif
+
+#ifndef errno
+#include
+#endif
+
+#include
+
+// Locations for searching the srb2.srb
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
+#define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2Kart"
+#define DEFAULTWADLOCATION2 "/usr/local/games/SRB2Kart"
+#define DEFAULTWADLOCATION3 "/usr/share/games/SRB2Kart"
+#define DEFAULTWADLOCATION4 "/usr/games/SRB2Kart"
+#define DEFAULTSEARCHPATH1 "/usr/local/games"
+#define DEFAULTSEARCHPATH2 "/usr/games"
+#define DEFAULTSEARCHPATH3 "/usr/local"
+#endif
+
+/** \brief WAD file to look for
+*/
+#define WADKEYWORD1 "srb2.srb"
+#define WADKEYWORD2 "srb2.wad"
+/** \brief holds wad path
+*/
+static char returnWadPath[256];
+
+#include "../doomdef.h"
+#include "../m_misc.h"
+#include "../i_video.h"
+#include "../i_sound.h"
+#include "../i_system.h"
+#include "../screen.h" //vid.WndParent
+#include "../d_net.h"
+#include "../g_game.h"
+#include "../filesrch.h"
+#include "../z_zone.h" // Z_Free
+#include "endtxt.h"
+
+#include "../i_joy.h"
+
+#include "../m_argv.h"
+
+#ifdef MAC_ALERT
+#include "macosx/mac_alert.h"
+#endif
+
+#include "../d_main.h"
+
+#if !defined(NOMUMBLE) && defined(HAVE_MUMBLE)
+// Mumble context string
+#include "../d_clisrv.h"
+#include "../byteptr.h"
+#endif
+
+#ifdef HAVE_LIBBACKTRACE
+#include
+// TODO - move this to some header file instead
+extern struct backtrace_state *bt_state;
+
+typedef struct bt_crash_reason_s {
+ enum {
+ BTCRASH_SIGNAL,
+ BTCRASH_ERRORMSG,
+ } type;
+
+ union {
+ INT32 signal;
+ const char *errormsg;
+ } value;
+} bt_crash_reason_t;
+
+#define BT_CRASH_REASON_SIGNAL(num) (bt_crash_reason_t){ .type = BTCRASH_SIGNAL, .value = { .signal = num } }
+#define BT_CRASH_REASON_ERRORMSG(msg) (bt_crash_reason_t){ .type = BTCRASH_ERRORMSG, .value = { .errormsg = msg } }
+
+static void printsignal(FILE *fp, INT32 num)
+{
+ switch (num)
+ {
+ case SIGILL:
+ fprintf(fp, "SIGILL - illegal instruction - invalid function image");
+ break;
+ case SIGFPE:
+ fprintf(fp, "SIGFPE - mathematical exception");
+ break;
+ case SIGSEGV:
+ fprintf(fp, "SIGSEGV - segment violation");
+ break;
+ case SIGABRT:
+ fprintf(fp, "SIGABRT - abnormal termination triggered by abort call");
+ break;
+ default:
+ fprintf(fp, "Signal number %d", num);
+ }
+}
+
+typedef struct bt_out_buf_s {
+ boolean error;
+ char *pos;
+ size_t size;
+} bt_out_buf_t;
+
+static void bt_syminfo_cb(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
+{
+ (void)symval;
+ (void)symsize;
+
+ bt_out_buf_t *buf = (bt_out_buf_t*)data;
+
+ if (!symname)
+ symname = "???";
+
+ int n = snprintf(buf->pos, buf->size, "%p %s\n", (void*)pc, symname);
+
+ if (n <= 0)
+ {
+ buf->size = 0;
+ return;
+ }
+
+ buf->pos += n;
+ buf->size -= n;
+}
+
+static int bt_simple_cb(void *data, uintptr_t pc)
+{
+ bt_out_buf_t *buf = (bt_out_buf_t*)data;
+
+ backtrace_syminfo(bt_state, pc, bt_syminfo_cb, NULL, data);
+
+ if (!buf->size) return 1;
+
+ return 0;
+}
+
+static int bt_full_cb(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
+{
+ bt_out_buf_t *buf = (bt_out_buf_t*)data;
+
+ if (!filename) filename = "???";
+ if (!function) function = "???";
+
+ int n = snprintf(buf->pos, buf->size, "%p %s\n\t%s:%d\n", (void*)pc, function, filename, lineno);
+
+ if (n <= 0) return 1;
+
+ buf->pos += n;
+ buf->size -= n;
+
+ if (!buf->size) return 1;
+
+ return 0;
+}
+
+static void bt_error_cb(void *data, const char *msg, int errnum)
+{
+ (void)msg; // We don't need this
+
+ bt_out_buf_t *buf = (bt_out_buf_t*)data;
+
+ // No debug info
+ if (errnum == -1)
+ buf->error = true;
+}
+
+static void write_backtrace(bt_crash_reason_t reason)
+{
+ FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "srb2kart-crash-log.txt"), "a");
+
+ time_t rawtime;
+ struct tm *timeinfo;
+
+ const size_t BUFSIZE = 8192;
+ char backtrace[BUFSIZE];
+
+ bt_out_buf_t buf;
+ buf.error = false;
+ buf.pos = backtrace;
+ buf.size = BUFSIZE;
+
+
+ if (!out)
+ {
+ fprintf(stderr, "\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n");
+ out = stderr;
+ }
+
+ // Get the current time as a string.
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+
+ fprintf(out, "------------------------\n\n");
+
+ fprintf(out, "Program name: %s %s\n", SRB2APPLICATION, VERSIONSTRING);
+
+ if (compdate && comptime && comprevision && compbranch)
+ fprintf(out, "Compiled: %s %s, commit %s, branch %s\n", compdate, comptime, comprevision, compbranch);
+
+ if (gamestate == GS_LEVEL)
+ {
+ char *title = G_BuildMapTitle(gamemap);
+
+ if (title)
+ {
+ fprintf(out, "Game map: %s (%s)\n", title, G_BuildMapName(gamemap));
+ Z_Free(title);
+ }
+ else
+ fprintf(out, "Game map: %s\n", G_BuildMapName(gamemap));
+ }
+
+ fprintf(out, "Time of crash: %s\n", asctime(timeinfo));
+
+ fprintf(out, "Caused by: ");
+
+ switch (reason.type)
+ {
+ case BTCRASH_SIGNAL:
+ printsignal(out, reason.value.signal);
+ break;
+
+ case BTCRASH_ERRORMSG:
+ fprintf(out, "%s", reason.value.errormsg);
+ break;
+ }
+
+ fprintf(out, "\nBacktrace:\n");
+
+ // Try to get full backtrace, it will print files and line numbers
+ backtrace_full(bt_state, 2, bt_full_cb, bt_error_cb, (void*)&buf);
+
+ if (buf.error)
+ {
+ // Fall back to simple backtrace, only prints function names
+ backtrace_simple(bt_state, 2, bt_simple_cb, NULL, (void*)&buf);
+ }
+
+ fputs(backtrace, out);
+
+ if (out != stderr)
+ {
+ fclose(out);
+ fprintf(stderr, "Crash report created, find srb2kart-crash-log.txt in your SRB2Kart directory\n");
+ }
+}
+
+#endif
+
+boolean consolevent = false;
+boolean framebuffer = false;
+
+boolean g_in_exiting_signal_handler = false;
+
+UINT8 keyboard_started = false;
+
+static void I_ReportSignal(int num, int coredumped)
+{
+ //static char msg[] = "oh no! back to reality!\r\n";
+ const char * sigmsg;
+ char msg[256];
+
+ switch (num)
+ {
+// case SIGINT:
+// sigmsg = "SIGINT - interrupted";
+// break;
+ case SIGILL:
+ sigmsg = "SIGILL - illegal instruction - invalid function image";
+ break;
+ case SIGFPE:
+ sigmsg = "SIGFPE - mathematical exception";
+ break;
+ case SIGSEGV:
+ sigmsg = "SIGSEGV - segment violation";
+ break;
+// case SIGTERM:
+// sigmsg = "SIGTERM - Software termination signal from kill";
+// break;
+// case SIGBREAK:
+// sigmsg = "SIGBREAK - Ctrl-Break sequence";
+// break;
+ case SIGABRT:
+ sigmsg = "SIGABRT - abnormal termination triggered by abort call";
+ break;
+ default:
+ sprintf(msg,"signal number %d", num);
+ if (coredumped)
+ sigmsg = 0;
+ else
+ sigmsg = msg;
+ }
+
+ if (coredumped)
+ {
+ if (sigmsg)
+ sprintf(msg, "%s (core dumped)", sigmsg);
+ else
+ strcat(msg, " (core dumped)");
+ }
+ else
+ {
+ sprintf(msg, "%s", sigmsg);
+ }
+
+#ifdef HAVE_LIBBACKTRACE
+ strncat(msg, "\n\nCrash report has been saved into srb2kart-crash-log.txt", 255);
+#elif defined(_WIN32) && !defined(__MINGW64__)
+ strncat(msg, "\n\nCrash report has been saved into srb2kart.rpt", 255);
+#endif
+
+ I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg);
+}
+
+#ifndef NEWSIGNALHANDLER
+FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
+{
+ g_in_exiting_signal_handler = true;
+
+ D_QuitNetGame(); // Fix server freezes
+
+#ifdef HAVE_LIBBACKTRACE
+ write_backtrace(BT_CRASH_REASON_SIGNAL(num));
+#endif
+
+ if (demo.recording)
+ G_SaveDemo();
+
+ I_ReportSignal(num, 0);
+ I_ShutdownSystem();
+ signal(num, SIG_DFL); //default signal action
+ raise(num);
+ I_Quit();
+}
+#endif
+
+FUNCNORETURN static ATTRNORETURN void quit_handler(int num)
+{
+ signal(num, SIG_DFL); //default signal action
+ raise(num);
+ I_Quit();
+}
+
+#ifdef HAVE_TERMIOS
+// TERMIOS console code from Quake3: thank you!
+boolean stdin_active = true;
+
+typedef struct
+{
+ size_t cursor;
+ char buffer[256];
+} feild_t;
+
+feild_t tty_con;
+
+// lock to prevent clearing partial lines, since not everything
+// printed ends on a newline.
+static boolean ttycon_ateol = true;
+// some key codes that the terminal may be using
+// TTimo NOTE: I'm not sure how relevant this is
+static INT32 tty_erase;
+static INT32 tty_eof;
+
+static struct termios tty_tc;
+
+// =============================================================
+// tty console routines
+// NOTE: if the user is editing a line when something gets printed to the early console then it won't look good
+// so we provide tty_Clear and tty_Show to be called before and after a stdout or stderr output
+// =============================================================
+
+// flush stdin, I suspect some terminals are sending a LOT of garbage
+// FIXME TTimo relevant?
+#if 0
+static inline void tty_FlushIn(void)
+{
+ char key;
+ while (read(STDIN_FILENO, &key, 1)!=-1);
+}
+#endif
+
+// do a backspace
+// TTimo NOTE: it seems on some terminals just sending '\b' is not enough
+// so for now, in any case we send "\b \b" .. yeah well ..
+// (there may be a way to find out if '\b' alone would work though)
+// Hanicef NOTE: using \b this way is unreliable because of terminal state,
+// it's better to use \r to reset the cursor to the beginning of the
+// line and clear from there.
+static void tty_Back(void)
+{
+ write(STDOUT_FILENO, "\r", 1);
+ if (tty_con.cursor>0)
+ {
+ write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
+ }
+ write(STDOUT_FILENO, " \b", 2);
+}
+
+static void tty_Clear(void)
+{
+ size_t i;
+ write(STDOUT_FILENO, "\r", 1);
+ if (tty_con.cursor>0)
+ {
+ for (i=0; i 0)
+ {
+ tty_con.cursor--;
+ tty_con.buffer[tty_con.cursor] = '\0';
+ tty_Back();
+ }
+ ev.data1 = KEY_BACKSPACE;
+ }
+ else if (key < ' ') // check if this is a control char
+ {
+ if (key == '\n')
+ {
+ tty_Clear();
+ tty_con.cursor = 0;
+ ev.data1 = KEY_ENTER;
+ }
+ else if (key == 0x4) // ^D, aka EOF
+ {
+ // shut down, most unix programs behave this way
+ I_Quit();
+ }
+ else continue;
+ }
+ else if (tty_con.cursor < sizeof(tty_con.buffer))
+ {
+ // push regular character
+ ev.data1 = tty_con.buffer[tty_con.cursor] = key;
+ tty_con.cursor++;
+ // print the current line (this is differential)
+ write(STDOUT_FILENO, &key, 1);
+ }
+ if (ev.data1) D_PostEvent(&ev);
+ }
+}
+
+#elif defined (_WIN32)
+static BOOL I_ReadyConsole(HANDLE ci)
+{
+ DWORD gotinput;
+ if (ci == INVALID_HANDLE_VALUE) return FALSE;
+ if (WaitForSingleObject(ci,0) != WAIT_OBJECT_0) return FALSE;
+ if (GetFileType(ci) != FILE_TYPE_CHAR) return FALSE;
+ if (!GetConsoleMode(ci, &gotinput)) return FALSE;
+ return (GetNumberOfConsoleInputEvents(ci, &gotinput) && gotinput);
+}
+
+static boolean entering_con_command = false;
+
+static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
+{
+ event_t event;
+ CONSOLE_SCREEN_BUFFER_INFO CSBI;
+ DWORD t;
+
+ memset(&event,0x00,sizeof (event));
+
+ if (evt.bKeyDown)
+ {
+ event.type = ev_console;
+ entering_con_command = true;
+ switch (evt.wVirtualKeyCode)
+ {
+ case VK_ESCAPE:
+ case VK_TAB:
+ event.data1 = KEY_NULL;
+ break;
+ case VK_RETURN:
+ entering_con_command = false;
+ // Fall through.
+ default:
+ //event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
+ event.data1 = evt.uChar.AsciiChar;
+ }
+ if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t))
+ {
+ if (event.data1 && event.data1 != KEY_LSHIFT && event.data1 != KEY_RSHIFT)
+ {
+#ifdef _UNICODE
+ WriteConsole(co, &evt.uChar.UnicodeChar, 1, &t, NULL);
+#else
+ WriteConsole(co, &evt.uChar.AsciiChar, 1 , &t, NULL);
+#endif
+ }
+ if (evt.wVirtualKeyCode == VK_BACK
+ && GetConsoleScreenBufferInfo(co,&CSBI))
+ {
+ WriteConsoleOutputCharacterA(co, " ",1, CSBI.dwCursorPosition, &t);
+ }
+ }
+ }
+ if (event.data1) D_PostEvent(&event);
+}
+
+void I_GetConsoleEvents(void)
+{
+ HANDLE ci = GetStdHandle(STD_INPUT_HANDLE);
+ HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE);
+ INPUT_RECORD input;
+ DWORD t;
+
+ while (I_ReadyConsole(ci) && ReadConsoleInput(ci, &input, 1, &t) && t)
+ {
+ switch (input.EventType)
+ {
+ case KEY_EVENT:
+ Impl_HandleKeyboardConsoleEvent(input.Event.KeyEvent, co);
+ break;
+ case MOUSE_EVENT:
+ case WINDOW_BUFFER_SIZE_EVENT:
+ case MENU_EVENT:
+ case FOCUS_EVENT:
+ break;
+ }
+ }
+}
+
+static void I_StartupConsole(void)
+{
+ HANDLE ci, co;
+ const INT32 ded = M_CheckParm("-dedicated");
+ BOOL gotConsole = FALSE;
+ if (M_CheckParm("-console") || ded)
+ gotConsole = AllocConsole();
+#ifdef _DEBUG
+ else if (M_CheckParm("-noconsole") && !ded)
+#else
+ else if (!M_CheckParm("-console") && !ded)
+#endif
+ {
+ FreeConsole();
+ gotConsole = FALSE;
+ }
+
+ if (gotConsole)
+ {
+ SetConsoleTitleA("SRB2Kart Console");
+ consolevent = true;
+ }
+
+ //Let get the real console HANDLE, because Mingw's Bash is bad!
+ ci = CreateFile(TEXT("CONIN$") , GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ co = CreateFile(TEXT("CONOUT$"), GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (ci != INVALID_HANDLE_VALUE)
+ {
+ const DWORD CM = ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT;
+ SetStdHandle(STD_INPUT_HANDLE, ci);
+ if (GetFileType(ci) == FILE_TYPE_CHAR)
+ SetConsoleMode(ci, CM); //default mode but no ENABLE_MOUSE_INPUT
+ }
+ if (co != INVALID_HANDLE_VALUE)
+ {
+ SetStdHandle(STD_OUTPUT_HANDLE, co);
+ SetStdHandle(STD_ERROR_HANDLE, co);
+ }
+}
+static inline void I_ShutdownConsole(void){}
+#else
+void I_GetConsoleEvents(void){}
+static inline void I_StartupConsole(void)
+{
+#ifdef _DEBUG
+ consolevent = !M_CheckParm("-noconsole");
+#else
+ consolevent = M_CheckParm("-console");
+#endif
+
+ framebuffer = M_CheckParm("-framebuffer");
+
+ if (framebuffer)
+ consolevent = false;
+}
+static inline void I_ShutdownConsole(void){}
+#endif
+
+//
+// StartupKeyboard
+//
+static void I_RegisterSignals (void)
+{
+#ifdef SIGINT
+ signal(SIGINT , quit_handler);
+#endif
+#ifdef SIGBREAK
+ signal(SIGBREAK , quit_handler);
+#endif
+#ifdef SIGTERM
+ signal(SIGTERM , quit_handler);
+#endif
+
+ // If these defines don't exist,
+ // then compilation would have failed above us...
+#ifndef NEWSIGNALHANDLER
+ signal(SIGILL , signal_handler);
+ signal(SIGSEGV , signal_handler);
+ signal(SIGABRT , signal_handler);
+ signal(SIGFPE , signal_handler);
+#endif
+}
+
+#ifdef NEWSIGNALHANDLER
+static void signal_handler_child(INT32 num)
+{
+#ifdef HAVE_LIBBACKTRACE
+ write_backtrace(BT_CRASH_REASON_SIGNAL(num));
+#endif
+
+ if (demo.recording)
+ G_SaveDemo();
+
+ signal(num, SIG_DFL); //default signal action
+ raise(num);
+}
+
+static void I_RegisterChildSignals(void)
+{
+ // If these defines don't exist,
+ // then compilation would have failed above us...
+ signal(SIGILL , signal_handler_child);
+ signal(SIGSEGV , signal_handler_child);
+ signal(SIGABRT , signal_handler_child);
+ signal(SIGFPE , signal_handler_child);
+}
+#endif
+
+//
+//I_OutputMsg
+//
+void I_OutputMsg(const char *fmt, ...)
+{
+ size_t len;
+ char *txt;
+ va_list argptr;
+
+ va_start(argptr,fmt);
+ len = vsnprintf(NULL, 0, fmt, argptr);
+ va_end(argptr);
+ if (len == 0)
+ return;
+
+ txt = malloc(len+1);
+ va_start(argptr,fmt);
+ vsprintf(txt, fmt, argptr);
+ va_end(argptr);
+
+#ifdef HAVE_TTF
+ if (TTF_WasInit()) I_TTFDrawText(currentfont, solid, DEFAULTFONTFGR, DEFAULTFONTFGG, DEFAULTFONTFGB, DEFAULTFONTFGA,
+ DEFAULTFONTBGR, DEFAULTFONTBGG, DEFAULTFONTBGB, DEFAULTFONTBGA, txt);
+#endif
+
+#if defined (_WIN32) && defined (_MSC_VER)
+ OutputDebugStringA(txt);
+#endif
+
+ len = strlen(txt);
+
+#ifdef LOGMESSAGES
+ if (logstream)
+ {
+ size_t d = fwrite(txt, len, 1, logstream);
+ fflush(logstream);
+ (void)d;
+ }
+#endif
+
+#if defined (_WIN32)
+#ifdef DEBUGFILE
+ if (debugfile != stderr)
+#endif
+ {
+ HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD bytesWritten;
+
+ if (co == INVALID_HANDLE_VALUE)
+ {
+ free(txt);
+ return;
+ }
+
+ if (GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &bytesWritten))
+ {
+ static COORD coordNextWrite = {0,0};
+ LPVOID oldLines = NULL;
+ INT oldLength;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ // Save the lines that we're going to obliterate.
+ GetConsoleScreenBufferInfo(co, &csbi);
+ oldLength = csbi.dwSize.X * (csbi.dwCursorPosition.Y - coordNextWrite.Y) + csbi.dwCursorPosition.X - coordNextWrite.X;
+
+ if (oldLength > 0)
+ {
+ LPVOID blank = malloc(oldLength);
+ if (!blank)
+ {
+ free(txt);
+ return;
+ }
+ memset(blank, ' ', oldLength); // Blank out.
+ oldLines = malloc(oldLength*sizeof(TCHAR));
+ if (!oldLines)
+ {
+ free(txt);
+ free(blank);
+ return;
+ }
+
+ ReadConsoleOutputCharacter(co, oldLines, oldLength, coordNextWrite, &bytesWritten);
+
+ // Move to where we what to print - which is where we would've been,
+ // had console input not been in the way,
+ SetConsoleCursorPosition(co, coordNextWrite);
+
+ WriteConsoleA(co, blank, oldLength, &bytesWritten, NULL);
+ free(blank);
+
+ // And back to where we want to print again.
+ SetConsoleCursorPosition(co, coordNextWrite);
+ }
+
+ // Actually write the string now!
+ WriteConsoleA(co, txt, (DWORD)len, &bytesWritten, NULL);
+
+ // Next time, output where we left off.
+ GetConsoleScreenBufferInfo(co, &csbi);
+ coordNextWrite = csbi.dwCursorPosition;
+
+ // Restore what was overwritten.
+ if (oldLines && entering_con_command)
+ WriteConsole(co, oldLines, oldLength, &bytesWritten, NULL);
+ if (oldLines) free(oldLines);
+ }
+ else // Redirected to a file.
+ WriteFile(co, txt, (DWORD)len, &bytesWritten, NULL);
+ }
+#else
+#ifdef HAVE_TERMIOS
+ if (consolevent && ttycon_ateol)
+ {
+ tty_Clear();
+ ttycon_ateol = false;
+ }
+#endif
+
+ if (!framebuffer)
+ fprintf(stderr, "%s", txt);
+#ifdef HAVE_TERMIOS
+ if (consolevent && txt[len-1] == '\n')
+ {
+ write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
+ ttycon_ateol = true;
+ }
+#endif
+
+ // 2004-03-03 AJR Since not all messages end in newline, some were getting displayed late.
+ if (!framebuffer)
+ fflush(stderr);
+
+#endif
+ free(txt);
+}
+
+//
+// I_GetKey
+//
+INT32 I_GetKey (void)
+{
+ // Warning: I_GetKey empties the event queue till next keypress
+ event_t *ev;
+ INT32 rc = 0;
+
+ // return the first keypress from the event queue
+ for (; eventtail != eventhead; eventtail = (eventtail+1)&(MAXEVENTS-1))
+ {
+ ev = &events[eventtail];
+ if (ev->type == ev_keydown || ev->type == ev_console)
+ {
+ rc = ev->data1;
+ continue;
+ }
+ }
+
+ return rc;
+}
+
+//
+// I_JoyScale
+//
+void I_JoyScale(void)
+{
+}
+
+void I_JoyScale2(void)
+{
+}
+
+void I_JoyScale3(void)
+{
+}
+
+void I_JoyScale4(void)
+{
+}
+
+/** \brief Shuts down joystick 1
+
+
+ \return void
+
+
+*/
+void I_ShutdownJoystick(void)
+{
+}
+
+void I_GetJoystickEvents(UINT8 index)
+{
+ (void)index;
+}
+
+//
+// I_InitJoystick
+//
+void I_InitJoystick(UINT8 index)
+{
+ (void)index;
+}
+
+void I_InitJoystick1(void)
+{
+}
+
+void I_InitJoystick2(void)
+{
+}
+
+void I_InitJoystick3(void)
+{
+}
+
+void I_InitJoystick4(void)
+{
+}
+
+INT32 I_NumJoys(void)
+{
+ return 0;
+}
+
+const char *I_GetJoyName(INT32 joyindex)
+{
+ (void)joyindex;
+ return NULL;
+}
+
+void I_GamepadRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
+{
+ (void)playernum;
+ (void)low_strength;
+ (void)high_strength;
+ (void)duration;
+}
+
+void I_SetGamepadIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 blue)
+{
+ (void)playernum;
+ (void)red;
+ (void)green;
+ (void)blue;
+}
+
+#ifndef NOMUMBLE
+#ifdef HAVE_MUMBLE
+// Best Mumble positional audio settings:
+// Minimum distance 3.0 m
+// Bloom 175%
+// Maximum distance 80.0 m
+// Minimum volume 50%
+#define DEG2RAD (0.017453292519943295769236907684883l) // TAU/360 or PI/180
+#define MUMBLEUNIT (64.0f) // FRACUNITS in a Meter
+
+static struct {
+#ifdef WINMUMBLE
+ UINT32 uiVersion;
+ DWORD uiTick;
+#else
+ UINT32 uiVersion;
+ UINT32 uiTick;
+#endif
+ float fAvatarPosition[3];
+ float fAvatarFront[3];
+ float fAvatarTop[3]; // defaults to Y-is-up (only used for leaning)
+ wchar_t name[256]; // game name
+ float fCameraPosition[3];
+ float fCameraFront[3];
+ float fCameraTop[3]; // defaults to Y-is-up (only used for leaning)
+ wchar_t identity[256]; // player id
+#ifdef WINMUMBLE
+ UINT32 context_len;
+#else
+ UINT32 context_len;
+#endif
+ unsigned char context[256]; // server/team
+ wchar_t description[2048]; // game description
+} *mumble = NULL;
+#endif // HAVE_MUMBLE
+
+static void I_SetupMumble(void)
+{
+#ifdef WINMUMBLE
+ HANDLE hMap = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink");
+ if (!hMap)
+ return;
+
+ mumble = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble));
+ if (!mumble)
+ CloseHandle(hMap);
+#elif defined (HAVE_SHM)
+ int shmfd;
+ char memname[256];
+
+ snprintf(memname, 256, "/MumbleLink.%d", getuid());
+ shmfd = shm_open(memname, O_RDWR, S_IRUSR | S_IWUSR);
+
+ if(shmfd < 0)
+ return;
+
+ mumble = mmap(NULL, sizeof(*mumble), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
+ if (mumble == MAP_FAILED)
+ mumble = NULL;
+#endif
+}
+
+void I_UpdateMumble(const mobj_t *mobj, const listener_t listener)
+{
+#ifdef HAVE_MUMBLE
+ double angle;
+ fixed_t anglef;
+
+ if (!mumble)
+ return;
+
+ if (mumble->uiVersion != 2) {
+ wcsncpy(mumble->name, L"SRB2Kart "VERSIONSTRINGW, 256);
+ wcsncpy(mumble->description, L"Sonic Robo Blast 2 Kart with integrated Mumble Link support.", 2048);
+ mumble->uiVersion = 2;
+ }
+ mumble->uiTick++;
+
+ if (!netgame || gamestate != GS_LEVEL) { // Zero out, but never delink.
+ mumble->fAvatarPosition[0] = mumble->fAvatarPosition[1] = mumble->fAvatarPosition[2] = 0.0f;
+ mumble->fAvatarFront[0] = 1.0f;
+ mumble->fAvatarFront[1] = mumble->fAvatarFront[2] = 0.0f;
+ mumble->fCameraPosition[0] = mumble->fCameraPosition[1] = mumble->fCameraPosition[2] = 0.0f;
+ mumble->fCameraFront[0] = 1.0f;
+ mumble->fCameraFront[1] = mumble->fCameraFront[2] = 0.0f;
+ return;
+ }
+
+ {
+ UINT8 *p = mumble->context;
+ WRITEMEM(p, server_context, 8);
+ WRITEINT16(p, gamemap);
+ mumble->context_len = (UINT32)(p - mumble->context);
+ }
+
+ if (mobj) {
+ mumble->fAvatarPosition[0] = FIXED_TO_FLOAT(mobj->x) / MUMBLEUNIT;
+ mumble->fAvatarPosition[1] = FIXED_TO_FLOAT(mobj->z) / MUMBLEUNIT;
+ mumble->fAvatarPosition[2] = FIXED_TO_FLOAT(mobj->y) / MUMBLEUNIT;
+
+ anglef = AngleFixed(mobj->angle);
+ angle = FIXED_TO_FLOAT(anglef)*DEG2RAD;
+ mumble->fAvatarFront[0] = (float)cos(angle);
+ mumble->fAvatarFront[1] = 0.0f;
+ mumble->fAvatarFront[2] = (float)sin(angle);
+ } else {
+ mumble->fAvatarPosition[0] = mumble->fAvatarPosition[1] = mumble->fAvatarPosition[2] = 0.0f;
+ mumble->fAvatarFront[0] = 1.0f;
+ mumble->fAvatarFront[1] = mumble->fAvatarFront[2] = 0.0f;
+ }
+
+ mumble->fCameraPosition[0] = FIXED_TO_FLOAT(listener.x) / MUMBLEUNIT;
+ mumble->fCameraPosition[1] = FIXED_TO_FLOAT(listener.z) / MUMBLEUNIT;
+ mumble->fCameraPosition[2] = FIXED_TO_FLOAT(listener.y) / MUMBLEUNIT;
+
+ anglef = AngleFixed(listener.angle);
+ angle = FIXED_TO_FLOAT(anglef)*DEG2RAD;
+ mumble->fCameraFront[0] = (float)cos(angle);
+ mumble->fCameraFront[1] = 0.0f;
+ mumble->fCameraFront[2] = (float)sin(angle);
+#else
+ (void)mobj;
+ (void)listener;
+#endif // HAVE_MUMBLE
+}
+#undef WINMUMBLE
+#endif // NOMUMBLE
+
+
+/** \brief empty ticcmd for player 1
+*/
+static ticcmd_t emptycmd;
+
+ticcmd_t *I_BaseTiccmd(void)
+{
+ return &emptycmd;
+}
+
+/** \brief empty ticcmd for player 2
+*/
+static ticcmd_t emptycmd2;
+
+ticcmd_t *I_BaseTiccmd2(void)
+{
+ return &emptycmd2;
+}
+
+/** \brief empty ticcmd for player 3
+ */
+static ticcmd_t emptycmd3;
+
+ticcmd_t *I_BaseTiccmd3(void)
+{
+ return &emptycmd3;
+}
+
+/** \brief empty ticcmd for player 4
+ */
+static ticcmd_t emptycmd4;
+
+ticcmd_t *I_BaseTiccmd4(void)
+{
+ return &emptycmd4;
+}
+
+//
+// I_GetTime
+// returns time in 1/TICRATE second tics
+//
+
+precise_t I_GetPreciseTime(void)
+{
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (precise_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
+#elif defined (_WIN32)
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ return (precise_t)counter.QuadPart;
+#else
+ return 0;
+#endif
+}
+
+UINT64 I_GetPrecisePrecision(void)
+{
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
+ return 1000000000;
+#elif defined (_WIN32)
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+ return (UINT64)frequency.QuadPart;
+#else
+ return 1000000;
+#endif
+}
+
+void I_StartupTimer(void){}
+
+void I_Sleep(UINT32 ms)
+{
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
+ struct timespec ts = {
+ .tv_sec = ms / 1000,
+ .tv_nsec = ms % 1000 * 1000000,
+ };
+ int status;
+ do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
+ while (status == EINTR);
+#elif defined (_WIN32)
+ Sleep(ms);
+#else
+ (void)ms;
+#warning No sleep function for this system!
+#endif
+}
+
+void I_SleepDuration(precise_t duration)
+{
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__)
+ UINT64 precision = I_GetPrecisePrecision();
+ struct timespec ts = {
+ .tv_sec = duration / precision,
+ .tv_nsec = duration * 1000000000 / precision % 1000000000,
+ };
+ int status;
+ do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
+ while (status == EINTR);
+#elif defined (MIN_SLEEP_DURATION_MS)
+ UINT64 precision = I_GetPrecisePrecision();
+ INT32 sleepvalue = cv_sleep.value;
+ UINT64 delaygranularity;
+ precise_t cur;
+ precise_t dest;
+
+ {
+ double gran = round(((double)(precision / 1000) * sleepvalue * MIN_SLEEP_DURATION_MS));
+ delaygranularity = (UINT64)gran;
+ }
+
+ cur = I_GetPreciseTime();
+ dest = cur + duration;
+
+ // the reason this is not dest > cur is because the precise counter may wrap
+ // two's complement arithmetic is our friend here, though!
+ // e.g. cur 0xFFFFFFFFFFFFFFFE = -2, dest 0x0000000000000001 = 1
+ // 0x0000000000000001 - 0xFFFFFFFFFFFFFFFE = 3
+ while ((INT64)(dest - cur) > 0)
+ {
+ // If our cv_sleep value exceeds the remaining sleep duration, use the
+ // hard sleep function.
+ if (sleepvalue > 0 && (dest - cur) > delaygranularity)
+ {
+ I_Sleep(sleepvalue);
+ }
+
+ // Otherwise, this is a spinloop.
+
+ cur = I_GetPreciseTime();
+ }
+#endif
+}
+
+#ifdef NEWSIGNALHANDLER
+FUNCNORETURN static ATTRNORETURN void newsignalhandler_Warn(const char *pr)
+{
+ char text[128];
+
+ snprintf(text, sizeof text,
+ "Error while setting up signal reporting: %s: %s",
+ pr,
+ strerror(errno)
+ );
+
+ I_OutputMsg("%s\n", text);
+
+ I_ShutdownConsole();
+ exit(-1);
+}
+
+static void I_Fork(void)
+{
+ int child;
+ int status;
+ int signum;
+ int c;
+
+ child = fork();
+
+ switch (child)
+ {
+ case -1:
+ newsignalhandler_Warn("fork()");
+ break;
+ case 0:
+ I_RegisterChildSignals();
+ break;
+ default:
+ if (logstream)
+ fclose(logstream);/* the child has this */
+
+ c = wait(&status);
+
+#ifdef LOGMESSAGES
+ /* By the way, exit closes files. */
+ logstream = fopen(logfilename, "at");
+#else
+ logstream = 0;
+#endif
+
+ if (c == -1)
+ {
+ kill(child, SIGKILL);
+ newsignalhandler_Warn("wait()");
+ }
+ else
+ {
+ if (WIFSIGNALED (status))
+ {
+ signum = WTERMSIG (status);
+#ifdef WCOREDUMP
+ I_ReportSignal(signum, WCOREDUMP (status));
+#else
+ I_ReportSignal(signum, 0);
+#endif
+ status = 128 + signum;
+ }
+ else if (WIFEXITED (status))
+ {
+ status = WEXITSTATUS (status);
+ }
+
+ I_ShutdownConsole();
+ exit(status);
+ }
+ }
+}
+#endif/*NEWSIGNALHANDLER*/
+
+INT32 I_StartupSystem(void)
+{
+ I_StartupConsole();
+#ifdef NEWSIGNALHANDLER
+ // This is useful when debugging. It lets GDB attach to
+ // the correct process easily.
+ if (!M_CheckParm("-nofork"))
+ I_Fork();
+#endif
+#ifdef HAVE_THREADS
+ I_start_threads();
+ I_AddExitFunc(I_stop_threads);
+#endif
+ I_RegisterSignals();
+#ifndef NOMUMBLE
+ I_SetupMumble();
+#endif
+ return 0;
+}
+
+//
+// I_Quit
+//
+void I_Quit(void)
+{
+ static boolean quiting = false;
+
+ /* prevent recursive I_Quit() */
+ if (quiting) goto death;
+ quiting = false;
+ I_ShutdownConsole();
+ M_SaveConfig(NULL); //save game config, cvars..
+#ifndef NONET
+ D_SaveBan(); // save the ban list
+#endif
+ G_SaveGameData(false); // Tails 12-08-2002
+ //added:16-02-98: when recording a demo, should exit using 'q' key,
+ // but sometimes we forget and use 'F10'.. so save here too.
+
+ if (demo.recording)
+ G_CheckDemoStatus();
+ if (metalrecording)
+ G_StopMetalRecording();
+
+ D_QuitNetGame();
+ I_ShutdownMusic();
+ I_ShutdownSound();
+ // use this for 1.28 19990220 by Kin
+ I_ShutdownGraphics();
+ I_ShutdownSystem();
+ /* if option -noendtxt is set, don't print the text */
+ if (!M_CheckParm("-noendtxt") && W_CheckNumForName("ENDOOM") != LUMPERROR)
+ {
+ printf("\r");
+ ShowEndTxt();
+ }
+ if (myargmalloc)
+ free(myargv); // Deallocate allocated memory
+death:
+ W_Shutdown();
+ exit(0);
+}
+
+void I_WaitVBL(INT32 count)
+{
+ count = 1;
+ I_Sleep(count);
+}
+
+void I_BeginRead(void)
+{
+}
+
+void I_EndRead(void)
+{
+}
+
+//
+// I_Error
+//
+/** \brief phuck recursive errors
+*/
+static INT32 errorcount = 0;
+
+/** \brief recursive error detecting
+*/
+static boolean shutdowning = false;
+
+void I_Error(const char *error, ...)
+{
+ va_list argptr;
+ char buffer[8192];
+
+ // recursive error detecting
+ if (shutdowning)
+ {
+ errorcount++;
+ // try to shutdown each subsystem separately
+ if (errorcount == 1)
+ I_ShutdownMusic();
+ if (errorcount == 2)
+ I_ShutdownSound();
+ if (errorcount == 3)
+ I_ShutdownGraphics();
+ if (errorcount == 4)
+ I_ShutdownSystem();
+ if (errorcount == 5)
+ {
+ M_SaveConfig(NULL);
+ G_SaveGameData(false);
+ }
+ if (errorcount > 20)
+ {
+ va_start(argptr, error);
+ vsprintf(buffer, error, argptr);
+ va_end(argptr);
+
+ I_OutputMsg("SRB2Kart %s Recursive Error", buffer);
+
+ W_Shutdown();
+ exit(-1); // recursive errors detected
+ }
+ }
+
+ shutdowning = true;
+
+ // Display error message in the console before we start shutting it down
+ va_start(argptr, error);
+ vsprintf(buffer, error, argptr);
+ va_end(argptr);
+ I_OutputMsg("\nI_Error(): %s\n", buffer);
+
+#ifdef HAVE_LIBBACKTRACE
+ write_backtrace(BT_CRASH_REASON_ERRORMSG(buffer));
+#endif
+ // ---
+
+ I_ShutdownConsole();
+
+ M_SaveConfig(NULL); // save game config, cvars..
+#ifndef NONET
+ D_SaveBan(); // save the ban list
+#endif
+ G_SaveGameData(false); // Tails 12-08-2002
+
+ // Shutdown. Here might be other errors.
+ if (demo.recording)
+ G_CheckDemoStatus();
+ if (metalrecording)
+ G_StopMetalRecording();
+
+ D_QuitNetGame();
+ I_ShutdownMusic();
+ I_ShutdownSound();
+ // use this for 1.28 19990220 by Kin
+ I_ShutdownGraphics();
+ I_ShutdownSystem();
+
+ W_Shutdown();
+
+#if defined (PARANOIA) && defined (__CYGWIN__)
+ *(INT32 *)2 = 4; //Alam: Debug!
+#endif
+
+ exit(-1);
+}
+
+/** \brief quit function table
+*/
+static quitfuncptr quit_funcs[MAX_QUIT_FUNCS]; /* initialized to all bits 0 */
+
+//
+// Adds a function to the list that need to be called by I_SystemShutdown().
+//
+void I_AddExitFunc(void (*func)())
+{
+ INT32 c;
+
+ for (c = 0; c < MAX_QUIT_FUNCS; c++)
+ {
+ if (!quit_funcs[c])
+ {
+ quit_funcs[c] = func;
+ break;
+ }
+ }
+}
+
+
+//
+// Removes a function from the list that need to be called by
+// I_SystemShutdown().
+//
+void I_RemoveExitFunc(void (*func)())
+{
+ INT32 c;
+
+ for (c = 0; c < MAX_QUIT_FUNCS; c++)
+ {
+ if (quit_funcs[c] == func)
+ {
+ while (c < MAX_QUIT_FUNCS-1)
+ {
+ quit_funcs[c] = quit_funcs[c+1];
+ c++;
+ }
+ quit_funcs[MAX_QUIT_FUNCS-1] = NULL;
+ break;
+ }
+ }
+}
+
+#if !(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON))
+static void Shittycopyerror(const char *name)
+{
+ I_OutputMsg(
+ "Error copying log file: %s: %s\n",
+ name,
+ strerror(errno)
+ );
+}
+
+static void Shittylogcopy(void)
+{
+ char buf[8192];
+ FILE *fp;
+ size_t r;
+ if (fseek(logstream, 0, SEEK_SET) == -1)
+ {
+ Shittycopyerror("fseek");
+ }
+ else if (( fp = fopen(logfilename, "wt") ))
+ {
+ while (( r = fread(buf, 1, sizeof buf, logstream) ))
+ {
+ if (fwrite(buf, 1, r, fp) < r)
+ {
+ Shittycopyerror("fwrite");
+ break;
+ }
+ }
+ if (ferror(logstream))
+ {
+ Shittycopyerror("fread");
+ }
+ fclose(fp);
+ }
+ else
+ {
+ Shittycopyerror(logfilename);
+ }
+}
+#endif/*!(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON))*/
+
+//
+// Closes down everything. This includes restoring the initial
+// palette and video mode, and removing whatever mouse, keyboard, and
+// timer routines have been installed.
+//
+// NOTE: Shutdown user funcs are effectively called in reverse order.
+//
+void I_ShutdownSystem(void)
+{
+ INT32 c;
+
+#ifndef NEWSIGNALHANDLER
+ I_ShutdownConsole();
+#endif
+
+ for (c = MAX_QUIT_FUNCS-1; c >= 0; c--)
+ if (quit_funcs[c])
+ (*quit_funcs[c])();
+#ifdef LOGMESSAGES
+ if (logstream)
+ {
+ I_OutputMsg("I_ShutdownSystem(): end of logstream.\n");
+#if !(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON))
+ Shittylogcopy();
+#endif
+ fclose(logstream);
+ logstream = NULL;
+ }
+#endif
+}
+
+void I_GetDiskFreeSpace(INT64 *freespace)
+{
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
+#if defined (SOLARIS) || defined (__HAIKU__)
+ *freespace = INT32_MAX;
+ return;
+#else // Both Linux and BSD have this, apparently.
+ struct statfs stfs;
+ if (statfs(".", &stfs) == -1)
+ {
+ *freespace = INT32_MAX;
+ return;
+ }
+ *freespace = stfs.f_bavail * stfs.f_bsize;
+#endif
+#elif defined (_WIN32)
+ static p_GetDiskFreeSpaceExA pfnGetDiskFreeSpaceEx = NULL;
+ static boolean testwin95 = false;
+ ULARGE_INTEGER usedbytes, lfreespace;
+
+ if (!testwin95)
+ {
+ pfnGetDiskFreeSpaceEx = (p_GetDiskFreeSpaceExA)(LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetDiskFreeSpaceExA");
+ testwin95 = true;
+ }
+ if (pfnGetDiskFreeSpaceEx)
+ {
+ if (pfnGetDiskFreeSpaceEx(NULL, &lfreespace, &usedbytes, NULL))
+ *freespace = lfreespace.QuadPart;
+ else
+ *freespace = INT32_MAX;
+ }
+ else
+ {
+ DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters;
+ GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector,
+ &NumberOfFreeClusters, &TotalNumberOfClusters);
+ *freespace = BytesPerSector*SectorsPerCluster*NumberOfFreeClusters;
+ }
+#else // Dummy for platform independent; 1GB should be enough
+ *freespace = 1024*1024*1024;
+#endif
+}
+
+char *I_GetUserName(void)
+{
+ static char username[MAXPLAYERNAME+1];
+ char *p;
+#ifdef _WIN32
+ DWORD i = MAXPLAYERNAME;
+
+ if (!GetUserNameA(username, &i))
+#endif
+ {
+ p = I_GetEnv("USER");
+ if (!p)
+ {
+ p = I_GetEnv("user");
+ if (!p)
+ {
+ p = I_GetEnv("USERNAME");
+ if (!p)
+ {
+ p = I_GetEnv("username");
+ if (!p)
+ {
+ return NULL;
+ }
+ }
+ }
+ }
+ strncpy(username, p, MAXPLAYERNAME);
+ }
+
+
+ if (strcmp(username, "") != 0)
+ return username;
+ return NULL; // dummy for platform independent version
+}
+
+INT32 I_mkdir(const char *dirname, INT32 unixright)
+{
+//[segabor]
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (__CYGWIN__) || defined (__OS2__)
+ return mkdir(dirname, unixright);
+#elif defined (_WIN32)
+ UNREFERENCED_PARAMETER(unixright); /// \todo should implement ntright under nt...
+ return CreateDirectoryA(dirname, NULL);
+#else
+ (void)dirname;
+ (void)unixright;
+ return false;
+#endif
+}
+
+char *I_GetEnv(const char *name)
+{
+ return getenv(name);
+}
+
+INT32 I_PutEnv(char *variable)
+{
+ return putenv(variable);
+}
+
+INT32 I_ClipboardCopy(const char *data, size_t size)
+{
+ (void)data;
+ (void)size;
+ return -1;
+}
+
+const char *I_ClipboardPaste(void)
+{
+ return NULL;
+}
+
+/** \brief The isWadPathOk function
+
+ \param path string path to check
+
+ \return if true, wad file found
+
+
+*/
+static boolean isWadPathOk(const char *path)
+{
+ char *wad3path = malloc(256);
+
+ if (!wad3path)
+ return false;
+
+ sprintf(wad3path, pandf, path, WADKEYWORD1);
+
+ if (FIL_ReadFileOK(wad3path))
+ {
+ free(wad3path);
+ return true;
+ }
+
+ sprintf(wad3path, pandf, path, WADKEYWORD2);
+
+ if (FIL_ReadFileOK(wad3path))
+ {
+ free(wad3path);
+ return true;
+ }
+
+ free(wad3path);
+ return false;
+}
+
+static void pathonly(char *s)
+{
+ size_t j;
+
+ for (j = strlen(s); j != (size_t)-1; j--)
+ if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
+ {
+ if (s[j] == ':') s[j+1] = 0;
+ else s[j] = 0;
+ return;
+ }
+}
+
+/** \brief search for srb2.srb in the given path
+
+ \param searchDir starting path
+
+ \return WAD path if not NULL
+
+
+*/
+static const char *searchWad(const char *searchDir)
+{
+ static char tempsw[256] = "";
+ filestatus_t fstemp;
+
+ strcpy(tempsw, WADKEYWORD1);
+ fstemp = filesearch(tempsw,searchDir,NULL,true,20);
+ if (fstemp == FS_FOUND)
+ {
+ pathonly(tempsw);
+ return tempsw;
+ }
+
+ strcpy(tempsw, WADKEYWORD2);
+ fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
+ if (fstemp == FS_FOUND)
+ {
+ pathonly(tempsw);
+ return tempsw;
+ }
+ return NULL;
+}
+
+/** \brief go through all possible paths and look for srb2.srb
+
+ \return path to srb2.srb if any
+*/
+static const char *locateWad(void)
+{
+ const char *envstr;
+ const char *WadPath;
+
+ I_OutputMsg("SRB2WADDIR");
+ // does SRB2WADDIR exist?
+ if (((envstr = I_GetEnv("SRB2WADDIR")) != NULL) && isWadPathOk(envstr))
+ return envstr;
+
+#ifndef NOCWD
+ I_OutputMsg(",.");
+ // examine current dir
+ strcpy(returnWadPath, ".");
+ if (isWadPathOk(returnWadPath))
+ return NULL;
+#endif
+
+
+#ifdef DEFAULTDIR
+ I_OutputMsg(",HOME/" DEFAULTDIR);
+ // examine user jart directory
+ if ((envstr = I_GetEnv("HOME")) != NULL)
+ {
+ sprintf(returnWadPath, "%s" PATHSEP DEFAULTDIR, envstr);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+ }
+#endif
+
+
+#ifdef CMAKECONFIG
+#ifndef NDEBUG
+ I_OutputMsg(","CMAKE_ASSETS_DIR);
+ strcpy(returnWadPath, CMAKE_ASSETS_DIR);
+ if (isWadPathOk(returnWadPath))
+ {
+ return returnWadPath;
+ }
+#endif
+#endif
+
+#ifdef __APPLE__
+ OSX_GetResourcesPath(returnWadPath);
+ I_OutputMsg(",%s", returnWadPath);
+ if (isWadPathOk(returnWadPath))
+ {
+ return returnWadPath;
+ }
+#endif
+
+ // examine default dirs
+#ifdef DEFAULTWADLOCATION1
+ I_OutputMsg(","DEFAULTWADLOCATION1);
+ strcpy(returnWadPath, DEFAULTWADLOCATION1);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+#endif
+#ifdef DEFAULTWADLOCATION2
+ I_OutputMsg(","DEFAULTWADLOCATION2);
+ strcpy(returnWadPath, DEFAULTWADLOCATION2);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+#endif
+#ifdef DEFAULTWADLOCATION3
+ I_OutputMsg(","DEFAULTWADLOCATION3);
+ strcpy(returnWadPath, DEFAULTWADLOCATION3);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+#endif
+#ifdef DEFAULTWADLOCATION4
+ I_OutputMsg(","DEFAULTWADLOCATION4);
+ strcpy(returnWadPath, DEFAULTWADLOCATION4);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+#endif
+#ifdef DEFAULTWADLOCATION5
+ I_OutputMsg(","DEFAULTWADLOCATION5);
+ strcpy(returnWadPath, DEFAULTWADLOCATION5);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+#endif
+#ifdef DEFAULTWADLOCATION6
+ I_OutputMsg(","DEFAULTWADLOCATION6);
+ strcpy(returnWadPath, DEFAULTWADLOCATION6);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+#endif
+#ifdef DEFAULTWADLOCATION7
+ I_OutputMsg(","DEFAULTWADLOCATION7);
+ strcpy(returnWadPath, DEFAULTWADLOCATION7);
+ if (isWadPathOk(returnWadPath))
+ return returnWadPath;
+#endif
+#ifndef NOHOME
+ // find in $HOME
+ I_OutputMsg(",HOME/" DEFAULTDIR);
+ if ((envstr = I_GetEnv("HOME")) != NULL)
+ {
+ char *tmp = malloc(strlen(envstr) + sizeof(PATHSEP) + sizeof(DEFAULTDIR));
+ strcpy(tmp, envstr);
+ strcat(tmp, PATHSEP);
+ strcat(tmp, DEFAULTDIR);
+ WadPath = searchWad(tmp);
+ free(tmp);
+ if (WadPath)
+ return WadPath;
+ }
+#endif
+#ifdef DEFAULTSEARCHPATH1
+ // find in /usr/local
+ I_OutputMsg(", in:"DEFAULTSEARCHPATH1);
+ WadPath = searchWad(DEFAULTSEARCHPATH1);
+ if (WadPath)
+ return WadPath;
+#endif
+#ifdef DEFAULTSEARCHPATH2
+ // find in /usr/games
+ I_OutputMsg(", in:"DEFAULTSEARCHPATH2);
+ WadPath = searchWad(DEFAULTSEARCHPATH2);
+ if (WadPath)
+ return WadPath;
+#endif
+#ifdef DEFAULTSEARCHPATH3
+ // find in ???
+ I_OutputMsg(", in:"DEFAULTSEARCHPATH3);
+ WadPath = searchWad(DEFAULTSEARCHPATH3);
+ if (WadPath)
+ return WadPath;
+#endif
+ // if nothing was found
+ return NULL;
+}
+
+const char *I_LocateWad(void)
+{
+ const char *waddir;
+
+ I_OutputMsg("Looking for WADs in: ");
+ waddir = locateWad();
+ I_OutputMsg("\n");
+
+ if (waddir)
+ {
+ // change to the directory where we found srb2.srb
+#if defined (_WIN32)
+ SetCurrentDirectoryA(waddir);
+#else
+ if (chdir(waddir) == -1)
+ I_OutputMsg("Couldn't change working directory\n");
+#endif
+ }
+ return waddir;
+}
+
+#ifdef __linux__
+#define MEMINFO_FILE "/proc/meminfo"
+#define MEMTOTAL "MemTotal:"
+#define MEMAVAILABLE "MemAvailable:"
+#define MEMFREE "MemFree:"
+#define CACHED "Cached:"
+#define BUFFERS "Buffers:"
+#define SHMEM "Shmem:"
+
+/* Parse the contents of /proc/meminfo (in buf), return value of "name"
+ * (example: MemTotal) */
+static long get_entry(const char* name, const char* buf)
+{
+ long val;
+ char* hit = strstr(buf, name);
+ if (hit == NULL) {
+ return -1;
+ }
+
+ errno = 0;
+ val = strtol(hit + strlen(name), NULL, 10);
+ if (errno != 0) {
+ CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno));
+ return -1;
+ }
+ return val;
+}
+#endif
+
+size_t I_GetFreeMem(size_t *total)
+{
+#ifdef FREEBSD
+ u_int v_free_count, v_page_size, v_page_count;
+ size_t size = sizeof(v_free_count);
+ sysctlbyname("vm.stats.vm.v_free_count", &v_free_count, &size, NULL, 0);
+ size = sizeof(v_page_size);
+ sysctlbyname("vm.stats.vm.v_page_size", &v_page_size, &size, NULL, 0);
+ size = sizeof(v_page_count);
+ sysctlbyname("vm.stats.vm.v_page_count", &v_page_count, &size, NULL, 0);
+
+ if (total)
+ *total = v_page_count * v_page_size;
+ return v_free_count * v_page_size;
+#elif defined (SOLARIS)
+ /* Just guess */
+ if (total)
+ *total = 32 << 20;
+ return 32 << 20;
+#elif defined (_WIN32)
+ MEMORYSTATUS info;
+
+ info.dwLength = sizeof (MEMORYSTATUS);
+ GlobalMemoryStatus( &info );
+ if (total)
+ *total = (size_t)info.dwTotalPhys;
+ return (size_t)info.dwAvailPhys;
+#elif defined (__OS2__)
+ UINT32 pr_arena;
+
+ if (total)
+ DosQuerySysInfo( QSV_TOTPHYSMEM, QSV_TOTPHYSMEM,
+ (PVOID) total, sizeof (UINT32));
+ DosQuerySysInfo( QSV_MAXPRMEM, QSV_MAXPRMEM,
+ (PVOID) &pr_arena, sizeof (UINT32));
+
+ return pr_arena;
+#elif defined (__linux__)
+ /* Linux */
+ char buf[1024];
+ char *memTag;
+ size_t freeKBytes;
+ size_t totalKBytes;
+ INT32 n;
+ INT32 meminfo_fd = -1;
+ long Cached;
+ long MemFree;
+ long Buffers;
+ long Shmem;
+ long MemAvailable = -1;
+
+ meminfo_fd = open(MEMINFO_FILE, O_RDONLY);
+ n = read(meminfo_fd, buf, 1023);
+ close(meminfo_fd);
+
+ if (n < 0)
+ {
+ // Error
+ if (total)
+ *total = 0L;
+ return 0;
+ }
+
+ buf[n] = '\0';
+ if ((memTag = strstr(buf, MEMTOTAL)) == NULL)
+ {
+ // Error
+ if (total)
+ *total = 0L;
+ return 0;
+ }
+
+ memTag += sizeof (MEMTOTAL);
+ totalKBytes = (size_t)atoi(memTag);
+
+ if ((memTag = strstr(buf, MEMAVAILABLE)) == NULL)
+ {
+ Cached = get_entry(CACHED, buf);
+ MemFree = get_entry(MEMFREE, buf);
+ Buffers = get_entry(BUFFERS, buf);
+ Shmem = get_entry(SHMEM, buf);
+ MemAvailable = Cached + MemFree + Buffers - Shmem;
+
+ if (MemAvailable == -1)
+ {
+ // Error
+ if (total)
+ *total = 0L;
+ return 0;
+ }
+ freeKBytes = MemAvailable;
+ }
+ else
+ {
+ memTag += sizeof (MEMAVAILABLE);
+ freeKBytes = atoi(memTag);
+ }
+
+ if (total)
+ *total = totalKBytes << 10;
+ return freeKBytes << 10;
+#else
+ // Guess 48 MB.
+ if (total)
+ *total = 48<<20;
+ return 48<<20;
+#endif
+}
+
+// note CPUAFFINITY code used to reside here
+void I_RegisterSysCommands(void) {}
+
+boolean I_InitNetwork(void)
+{
+ // this must exist, but this is actually handled in i_tcp.c
+ return false;
+}
diff --git a/src/dedicated/i_threads.c b/src/dedicated/i_threads.c
new file mode 100644
index 000000000..f981fa961
--- /dev/null
+++ b/src/dedicated/i_threads.c
@@ -0,0 +1,364 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 2020-2023 by James R.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file i_threads.c
+/// \brief Multithreading abstraction
+
+#if defined (__unix__) || (!defined(__APPLE__) && defined (UNIXCOMMON))
+
+#include
+
+#include "../i_threads.h"
+#include "../doomdef.h"
+
+typedef struct thread_s thread_t;
+
+struct thread_s
+{
+ thread_t *next;
+ void *userdata;
+ I_thread_fn func;
+ pthread_t thread;
+};
+
+// we use a linked list to avoid moving memory blocks when allocating new threads.
+static thread_t *thread_list;
+static pthread_mutex_t thread_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static void *HandleThread(void *data)
+{
+ thread_t *thread = data;
+ thread->func(thread->userdata);
+
+ pthread_mutex_lock(&thread_lock);
+ thread->func = NULL;
+ pthread_mutex_unlock(&thread_lock);
+ return NULL;
+}
+
+void
+I_spawn_thread (
+ const char * name,
+ I_thread_fn entry,
+ void * userdata
+)
+{
+ thread_t *thread;
+ (void)name;
+
+ pthread_mutex_lock(&thread_lock);
+ thread = thread_list;
+ while (thread != NULL)
+ {
+ if (thread->func == NULL)
+ {
+ // join with the exited thread to release it's resources.
+ pthread_join(thread->thread, NULL);
+ break;
+ }
+ thread = thread->next;
+ }
+ if (thread == NULL)
+ {
+ thread = malloc(sizeof(thread_t));
+ thread->next = thread_list;
+ thread_list = thread;
+ }
+
+ thread->func = entry;
+ thread->userdata = userdata;
+ pthread_create(&thread->thread, NULL, HandleThread, thread);
+ pthread_mutex_unlock(&thread_lock);
+}
+
+int I_thread_is_stopped(void)
+{
+ thread_t *thread;
+ pthread_mutex_lock(&thread_lock);
+ thread = thread_list;
+ while (thread != NULL)
+ {
+ if (thread->func != NULL)
+ {
+ pthread_mutex_unlock(&thread_lock);
+ return false;
+ }
+ thread = thread->next;
+ }
+ pthread_mutex_unlock(&thread_lock);
+ return true;
+}
+
+void I_start_threads(void)
+{
+}
+
+void I_stop_threads(void)
+{
+ thread_t *thread = thread_list;
+ while (thread != NULL)
+ {
+ // join with all threads here, since finished threads haven't been awaited yet.
+ pthread_join(thread->thread, NULL);
+ thread = thread->next;
+ }
+}
+
+void I_lock_mutex(I_mutex *anchor)
+{
+ pthread_mutex_lock(&thread_lock);
+ if (*anchor == NULL)
+ {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+
+ // SRB2 relies on lock recursion, so we need a mutex configured for that.
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ *anchor = malloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init(*anchor, &attr);
+ pthread_mutexattr_destroy(&attr);
+ }
+ pthread_mutex_unlock(&thread_lock);
+ pthread_mutex_lock(*anchor);
+}
+
+void I_unlock_mutex(I_mutex id)
+{
+ pthread_mutex_unlock(id);
+}
+
+void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id)
+{
+ I_Assert(mutex_id != NULL);
+ pthread_mutex_lock(&thread_lock);
+ if (*cond_anchor == NULL)
+ {
+ *cond_anchor = malloc(sizeof(pthread_cond_t));
+ pthread_cond_init(*cond_anchor, NULL);
+ }
+ pthread_mutex_unlock(&thread_lock);
+ pthread_cond_wait(*cond_anchor, mutex_id);
+}
+
+void I_wake_one_cond(I_cond *anchor)
+{
+ pthread_mutex_lock(&thread_lock);
+ if (*anchor == NULL)
+ {
+ *anchor = malloc(sizeof(pthread_cond_t));
+ pthread_cond_init(*anchor, NULL);
+ }
+ pthread_mutex_unlock(&thread_lock);
+ pthread_cond_signal(*anchor);
+}
+
+void I_wake_all_cond(I_cond *anchor)
+{
+ pthread_mutex_lock(&thread_lock);
+ if (*anchor == NULL)
+ {
+ *anchor = malloc(sizeof(pthread_cond_t));
+ pthread_cond_init(*anchor, NULL);
+ }
+ pthread_mutex_unlock(&thread_lock);
+ pthread_cond_broadcast(*anchor);
+}
+#elif defined (_WIN32)
+#include
+
+#include "../i_threads.h"
+#include "../doomdef.h"
+#include "../doomtype.h"
+
+typedef struct thread_s thread_t;
+
+struct thread_s
+{
+ thread_t *next;
+ void *userdata;
+ I_thread_fn func;
+ HANDLE thread;
+ DWORD thread_id;
+};
+
+// we use a linked list to avoid moving memory blocks when allocating new threads.
+static thread_t *thread_list;
+static CRITICAL_SECTION thread_lock;
+
+static DWORD __stdcall HandleThread(void *data)
+{
+ thread_t *thread = data;
+ thread->func(thread->userdata);
+
+ EnterCriticalSection(&thread_lock);
+ thread->func = NULL;
+ LeaveCriticalSection(&thread_lock);
+ return 0;
+}
+
+void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata)
+{
+ thread_t *thread;
+ (void)name;
+ EnterCriticalSection(&thread_lock);
+ thread = thread_list;
+ while (thread != NULL)
+ {
+ if (thread->func == NULL)
+ {
+ CloseHandle(thread->thread);
+ break;
+ }
+ thread = thread->next;
+ }
+ if (thread == NULL)
+ {
+ thread = malloc(sizeof(thread_t));
+ thread->next = thread_list;
+ thread_list = thread;
+ }
+
+ thread->func = entry;
+ thread->userdata = userdata;
+ thread->thread = CreateThread(NULL, 0, HandleThread, thread, 0, &thread->thread_id);
+ LeaveCriticalSection(&thread_lock);
+}
+
+int I_thread_is_stopped(void)
+{
+ thread_t *thread;
+ EnterCriticalSection(&thread_lock);
+ thread = thread_list;
+ while (thread != NULL)
+ {
+ if (thread->func != NULL)
+ {
+ LeaveCriticalSection(&thread_lock);
+ return false;
+ }
+ thread = thread->next;
+ }
+ LeaveCriticalSection(&thread_lock);
+ return true;
+}
+
+void I_start_threads(void)
+{
+ InitializeCriticalSection(&thread_lock);
+}
+
+void I_stop_threads(void)
+{
+ thread_t *thread = thread_list;
+ while (thread != NULL)
+ {
+ WaitForSingleObject(thread->thread, INFINITE);
+ CloseHandle(thread->thread);
+ thread = thread->next;
+ }
+ DeleteCriticalSection(&thread_lock);
+}
+
+void I_lock_mutex(I_mutex *anchor)
+{
+ EnterCriticalSection(&thread_lock);
+ if (*anchor == NULL)
+ {
+ *anchor = malloc(sizeof(CRITICAL_SECTION));
+ InitializeCriticalSection(*anchor);
+ }
+ LeaveCriticalSection(&thread_lock);
+ EnterCriticalSection(*anchor);
+}
+
+void I_unlock_mutex(I_mutex id)
+{
+ LeaveCriticalSection(id);
+}
+
+void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id)
+{
+ I_Assert(mutex_id != NULL);
+ EnterCriticalSection(&thread_lock);
+ if (*cond_anchor == NULL)
+ {
+ *cond_anchor = malloc(sizeof(CONDITION_VARIABLE));
+ InitializeConditionVariable(*cond_anchor);
+ }
+ LeaveCriticalSection(&thread_lock);
+ SleepConditionVariableCS(*cond_anchor, mutex_id, INFINITE);
+}
+
+void I_wake_one_cond(I_cond *anchor)
+{
+ EnterCriticalSection(&thread_lock);
+ if (*anchor == NULL)
+ {
+ *anchor = malloc(sizeof(CONDITION_VARIABLE));
+ InitializeConditionVariable(*anchor);
+ }
+ LeaveCriticalSection(&thread_lock);
+ WakeConditionVariable(*anchor);
+}
+
+void I_wake_all_cond(I_cond *anchor)
+{
+ EnterCriticalSection(&thread_lock);
+ if (*anchor == NULL)
+ {
+ *anchor = malloc(sizeof(CONDITION_VARIABLE));
+ InitializeConditionVariable(*anchor);
+ }
+ LeaveCriticalSection(&thread_lock);
+ WakeAllConditionVariable(*anchor);
+}
+#else
+void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata)
+{
+ (void)name;
+ entry(userdata);
+}
+
+int I_thread_is_stopped(void)
+{
+}
+
+void I_start_threads(void)
+{
+}
+
+void I_stop_threads(void)
+{
+}
+
+void I_lock_mutex(I_mutex *anchor)
+{
+ (void)anchor;
+}
+
+void I_unlock_mutex(I_mutex id)
+{
+ (void)id;
+}
+
+void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id)
+{
+ (void)cond_anchor;
+ (void)mutex_id;
+}
+
+void I_wake_one_cond(I_cond *anchor)
+{
+ (void)anchor;
+}
+
+void I_wake_all_cond(I_cond *anchor)
+{
+ (void)anchor;
+}
+#endif
diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c
new file mode 100644
index 000000000..6c0b6644a
--- /dev/null
+++ b/src/dedicated/i_video.c
@@ -0,0 +1,154 @@
+// Emacs style mode select -*- C++ -*-
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 1993-1996 by id Software, Inc.
+// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
+// Copyright (C) 2014-2018 by Sonic Team Junior.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//-----------------------------------------------------------------------------
+/// \file
+/// \brief SRB2 graphics stuff for dedicated
+
+#include "../doomdef.h"
+#include "../i_system.h"
+#include "../i_video.h"
+#include "../console.h"
+#include "../command.h"
+#include "../i_system.h"
+#include "../screen.h"
+
+rendermode_t rendermode = render_none;
+
+boolean highcolor = false;
+
+// synchronize page flipping with screen refresh
+consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+static CV_PossibleValue_t keyboardlayout_cons_t[] = {{1,"Default US"}, {2, "Native"}, {3, "AZERTY"}, {0, NULL}};
+consvar_t cv_keyboardlayout = {"keyboardlayout", "Default US", CV_SAVE, keyboardlayout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+INT32 numcontrollers = 0;
+
+UINT8 graphics_started = 0; // Is used in console.c and screen.c
+
+// To disable fullscreen at startup; is set in VID_PrepareModeList
+boolean allow_fullscreen = false;
+UINT16 realwidth = BASEVIDWIDTH;
+UINT16 realheight = BASEVIDHEIGHT;
+
+extern boolean consolevent;
+
+void I_GetConsoleEvents(void);
+
+void I_GetEvent(void)
+{
+}
+
+void I_StartupMouse(void)
+{
+}
+
+//
+// I_OsPolling
+//
+void I_OsPolling(void)
+{
+ if (consolevent)
+ I_GetConsoleEvents();
+}
+
+//
+// I_UpdateNoBlit
+//
+void I_UpdateNoBlit(void)
+{
+}
+
+//
+// I_FinishUpdate
+//
+void I_FinishUpdate(void)
+{
+}
+
+//
+// I_UpdateNoVsync
+//
+void I_UpdateNoVsync(void)
+{
+}
+
+//
+// I_ReadScreen
+//
+void I_ReadScreen(UINT8 *scr)
+{
+ (void)scr;
+}
+
+//
+// I_SetPalette
+//
+void I_SetPalette(RGBA_t *palette)
+{
+ (void)palette;
+}
+
+// return number of fullscreen + X11 modes
+INT32 VID_NumModes(void)
+{
+ return 0;
+}
+
+const char *VID_GetModeName(INT32 modenum)
+{
+ (void)modenum;
+ return NULL;
+}
+
+INT32 VID_GetModeForSize(INT32 w, INT32 h)
+{
+ (void)w;
+ (void)h;
+ return -1;
+}
+
+void VID_PrepareModeList(void)
+{
+}
+
+INT32 VID_SetMode(INT32 modeNum)
+{
+ (void)modeNum;
+ return true;
+}
+
+void I_StartupGraphics(void)
+{
+}
+
+void I_ShutdownGraphics(void)
+{
+}
+
+UINT32 I_GetRefreshRate(void)
+{
+ return 0;
+}
+
+boolean I_UseNativeKeyboard(void)
+{
+ return false;
+}
diff --git a/src/g_game.c b/src/g_game.c
index 200ce7834..3d2f37fac 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -8117,9 +8117,6 @@ void G_SaveDemo(void)
UINT8 *p = demobuf.buffer+16; // after version
UINT32 length;
-#ifdef NOMD5
- UINT8 i;
-#endif
// Ensure extrainfo pointer is always available, even if no info is present.
if (demoinfo_p && *(UINT32 *)demoinfo_p == 0)
@@ -8174,7 +8171,7 @@ void G_SaveDemo(void)
length = *(UINT32 *)demoinfo_p;
WRITEUINT32(demoinfo_p, length);
#ifdef NOMD5
- for (i = 0; i < 16; i++, p++)
+ for (UINT8 k = 0; k < 16; k++, p++)
*p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
// Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable.
diff --git a/src/hardware/Sourcefile b/src/hardware/Sourcefile
new file mode 100644
index 000000000..3114c975c
--- /dev/null
+++ b/src/hardware/Sourcefile
@@ -0,0 +1,14 @@
+hw_bsp.c
+hw_draw.c
+hw_main.c
+hw_clip.c
+hw_md2.c
+hw_cache.c
+hw_md2load.c
+hw_md3load.c
+hw_model.c
+hw_portal.c
+hw_batching.c
+hw_shaders.c
+u_list.c
+r_opengl/r_opengl.c
diff --git a/src/m_menu.c b/src/m_menu.c
index 2fb38a4d5..842f22d44 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -7133,7 +7133,7 @@ static void DrawReplayHutReplayInfo(void)
case MD_OUTDATED:
V_DrawThinString(17, 64, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, va("Recorded on an outdated version. %s", demolist[dir_on[menudepthleft]].version));
- /*fallthru*/
+ /* FALLTHRU */
default:
// Draw level stuff
x = 15; y = 15;
diff --git a/src/m_misc.c b/src/m_misc.c
index c44086f4c..9455608cb 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -55,12 +55,13 @@
#ifdef HAVE_SDL
#include "sdl/hwsym_sdl.h"
+#endif
+
#ifdef __linux__
#ifndef _LARGEFILE64_SOURCE
typedef off_t off64_t;
#endif
#endif
-#endif
#if defined(__MINGW32__) && ((__GNUC__ > 7) || (__GNUC__ == 6 && __GNUC_MINOR__ >= 3)) && (__GNUC__ < 8)
#define PRIdS "u"
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 0157963f9..06cbd3b17 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -7025,7 +7025,7 @@ void P_MobjThinker(mobj_t *mobj)
P_RemoveMobj(mobj);
return;
}
- // fallthru
+ /* FALLTHRU */
case MT_ORBINAUT_SHIELD:
case MT_BANANA_SHIELD:
case MT_EGGMANITEM_SHIELD:
@@ -7035,7 +7035,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_JAWZ_DUD:
if (P_IsObjectOnGround(mobj))
P_SetMobjState(mobj, mobj->info->xdeathstate);
- // fallthru
+ /* FALLTHRU */
case MT_JAWZ_SHIELD:
mobj->flags2 ^= MF2_DONTDRAW;
break;
diff --git a/src/sdl/MakeCYG.cfg b/src/sdl/MakeCYG.cfg
deleted file mode 100644
index b78316b00..000000000
--- a/src/sdl/MakeCYG.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# sdl/makeCYG.cfg for SRB2/Cygwin
-#
-
-#
-#Cygwin, for debugging
-
- NOHW=1
- NOHS=1
-
- OPTS+=-DLINUX
-
- i_system_o+=$(OBJDIR)/SRB2.res
-
- # name of the exefile
- EXENAME?=lsdlsrb2.exe
diff --git a/src/sdl/MakeNIX.cfg b/src/sdl/MakeNIX.cfg
deleted file mode 100644
index 81991793e..000000000
--- a/src/sdl/MakeNIX.cfg
+++ /dev/null
@@ -1,76 +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
-
-#Use -rdynamic so a backtrace log shows function names instead of addresses
- LDFLAGS+=-rdynamic
-
- #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
- 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+=-lkvm -lexecinfo
-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?=lsdl2srb2kart
diff --git a/src/sdl/Makefile.cfg b/src/sdl/Makefile.cfg
deleted file mode 100644
index 3cf04509b..000000000
--- a/src/sdl/Makefile.cfg
+++ /dev/null
@@ -1,106 +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
-
-
- 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
- SDL_LDFLAGS+=-lSDL2_mixer
-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 NOLIBBACKTRACE
- OPTS+=-DHAVE_LIBBACKTRACE
-ifdef MINGW64
- CPPFLAGS+=-I../libs/libbacktrace/include
- LDFLAGS+=-L../libs/libbacktrace/lib/x86_64
-endif
- LIBS:=-lbacktrace $(LIBS)
-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/i_main.c b/src/sdl/i_main.c
index d6a007919..f033b678a 100644
--- a/src/sdl/i_main.c
+++ b/src/sdl/i_main.c
@@ -20,7 +20,7 @@
#include "../doomdef.h"
#include "../m_argv.h"
#include "../d_main.h"
-#include "../m_misc.h"/* path shit */
+#include "../m_misc.h" /* path shit */
#include "../i_system.h"
#if defined (__GNUC__) || defined (__unix__)
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index b0890913a..afda0caa2 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -743,7 +743,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
break;
case VK_RETURN:
entering_con_command = false;
- // Fall through.
+ /* FALLTHRU */
default:
//event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
event.data1 = evt.uChar.AsciiChar;
diff --git a/src/w_wad.c b/src/w_wad.c
index 0c7fdbaf0..ff2938c3e 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -724,7 +724,9 @@ UINT16 W_InitFile(const char *filename, boolean local)
wadfile_t *wadfile;
restype_t type;
UINT16 numlumps = 0;
+#ifndef NOMD5
size_t i;
+#endif
UINT8 md5sum[16];
boolean important;
diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg
deleted file mode 100644
index 4f8b39485..000000000
--- a/src/win32/Makefile.cfg
+++ /dev/null
@@ -1,154 +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 -lopenmpt
-endif
-
- 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
-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 -lopenmpt
-endif
- 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
-
-ifndef NONET
-ifndef MINGW64 #miniupnc is broken with MINGW64
- HAVE_MINIUPNPC=1
-endif
-endif
-
-ifndef NO_DISCORDRPC
- HAVE_DISCORDRPC=1
-endif
-
- OPTS=-DSTDC_HEADERS
-
-ifndef GCC44
- #OPTS+=-mms-bitfields
-endif
-
- OPTS+=-D__USE_MINGW_ANSI_STDIO=0
-
- LIBS+=-ladvapi32 -lkernel32 -lmsvcrt -luser32
-ifdef MINGW64
- LIBS+=-lws2_32
-else
-ifdef NO_IPV6
- LIBS+=-lwsock32
-else
- LIBS+=-lws2_32
-endif
-endif
-
-ifndef MINGW64
- CPPFLAGS+=-I../libs/drmingw/include
- LDFLAGS+=-L../libs/drmingw/lib/win32
- LIBS+=-lmgwhelp -lexchndl
-endif
-
- # name of the exefile
- EXENAME?=srb2kart-saturn.exe
-
- i_system_o+=$(OBJDIR)/SRB2.res
- #i_main_o+=$(OBJDIR)/win_dbg.o
-ifndef NOHW
- OPTS+=-DUSE_WGL_SWAP
-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
-
-ifdef HAVE_DISCORDRPC
-ifdef MINGW64
- CPPFLAGS+=-I../libs/discord-rpc/win64-dynamic/include
- LDFLAGS+=-L../libs/discord-rpc/win64-dynamic/lib
-else
- CPPFLAGS+=-I../libs/discord-rpc/win32-dynamic/include
- LDFLAGS+=-L../libs/discord-rpc/win32-dynamic/lib
-endif
- LIBS+=-ldiscord-rpc
-endif
-
-ifndef MINGW64
- LDFLAGS+=-Wl,--large-address-aware
-endif
-
-ifndef MINGW64
- NOLIBBACKTRACE=1
-endif
-
-# disable dynamicbase if under msys2
-ifdef MSYSTEM
- LDFLAGS+=-Wl,--disable-dynamicbase
-endif