diff --git a/.gitignore b/.gitignore
index 3090417dd6b00b8796d2743675301615e488707d..7023aaa80b08949f6d1a1a9d35ff413e5dd02a3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,11 +13,11 @@ Win32_LIB_ASM_Release
 *.dgb
 *.debug
 *.debug.txt
-/bin/VC10/
-/objs/VC10/
 *.user
 *.db
 *.opendb
 /.vs
 /debian
 /assets/debian
+/make
+/bin
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d2d4a7e65982e052c9d8cb222e30fe4fcefe393..148f17ef05ad96ca45fd74e9065b78e1aa1e6d57 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -119,7 +119,7 @@ set(SRB2_SDL2_EXE_NAME srb2 CACHE STRING "Executable binary output name")
 include_directories(${CMAKE_CURRENT_BINARY_DIR}/src)
 
 add_subdirectory(src)
-add_subdirectory(assets)
+#add_subdirectory(assets)
 
 
 ## config.h generation
diff --git a/src/Makefile b/src/Makefile
index cf06ce90461a551d5cb031393059778606a20f41..dafec3645a968800fd10f98db67e90c104e2adde 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,817 +1,402 @@
-
-#     GNU Make makefile for SRB2
-#############################################################################
-# Copyright (C) 1998-2000 by DooM Legacy Team.
-# Copyright (C) 2003-2021 by Sonic Team Junior.
+# GNU Makefile for SRB2
+# the poly3 Makefile adapted over and over...
+#
+# Copyright 1998-2000 DooM Legacy Team.
+# Copyright 2020-2021 James R.
+# Copyright 2003-2021 Sonic Team Junior.
 #
 # This program is free software distributed under the
 # terms of the GNU General Public License, version 2.
 # See the 'LICENSE' file for more details.
 #
-#     -DLINUX     -> use for the GNU/Linux specific
-#     -D_WINDOWS  -> use for the Win32/DirectX specific
-#     -DHAVE_SDL  -> use for the SDL interface
+# Special targets:
 #
-# Sets:
-#     Compile the SDL/Mingw version with 'make MINGW=1'
-#     Compile the SDL/Linux version with 'make LINUX=1'
-#     Compile the SDL/Solaris version with 'make SOLARIS=1'
-#     Compile the SDL/FreeBSD version with 'gmake FREEBSD=1'
-#     Compile the SDL/Cygwin version with 'make CYGWIN32=1'
-#     Compile the SDL/other version try with 'make SDL=1'
+# clean - remove executables and objects for this build
+# cleandep - remove dependency files for this build
+# distclean - remove entire executable, object and
+#             dependency file directory structure.
+# info - print settings
 #
-# 'Targets':
-#     clean
-#       Remove all object files
-#     cleandep
-#       Remove dependency files
-#     distclean
-#       Remove autogenerated files
-#     dll
-#       compile primary HW render DLL/SO
-#     all_dll
-#       compile all HW render and 3D sound DLLs for the set
-#     opengl_dll
-#       Pure Mingw only, compile OpenGL HW render DLL
-#     ds3d_dll
-#       Pure Mingw only, compile DirectX DirectSound HW sound DLL
-#     fmod_dll
-#       Pure Mingw only, compile FMOD HW sound DLL
-#     openal_dll
-#       Pure Mingw only, compile OpenAL HW sound DLL
-#     fmod_so
-#       Non-Mingw, compile FMOD HW sound SO
-#     openal_so
-#       Non-Mingw, compile OpenAL HW sound SO
+# This Makefile can automatically detect the host system
+# as well as the compiler version. If system or compiler
+# version cannot be detected, you may need to set a flag
+# manually.
 #
+# On Windows machines, 32-bit Windows is always targetted.
 #
-# Addon:
-#     To Cross-Compile, CC=gcc-version make * PREFIX=<dir>
-#     Compile with GCC 2.97 version, add 'GCC29=1'
-#     Compile with GCC 4.0x version, add 'GCC40=1'
-#     Compile with GCC 4.1x version, add 'GCC41=1'
-#     Compile with GCC 4.2x version, add 'GCC42=1'
-#     Compile with GCC 4.3x version, add 'GCC43=1'
-#     Compile with GCC 4.4x version, add 'GCC44=1'
-#     Compile with GCC 4.5x version, add 'GCC45=1'
-#     Compile with GCC 4.6x version, add 'GCC46=1'
-#     Compile a profile version, add 'PROFILEMODE=1'
-#     Compile a debug version, add 'DEBUGMODE=1'
-#     Compile with less warnings, add 'RELAXWARNINGS=1'
-#     Generate compiler errors for most compiler warnings, add 'ERRORMODE=1'
-#     Compile without NASM's tmap.nas, add 'NOASM=1'
-#     Compile without 3D hardware support, add 'NOHW=1'
-#     Compile with GDBstubs, add 'RDB=1'
-#     Compile without PNG, add 'NOPNG=1'
-#     Compile without zlib, add 'NOZLIB=1'
+# Platform/system flags:
 #
-# Addon for SDL:
-#     To Cross-Compile, add 'SDL_CONFIG=/usr/*/bin/sdl-config'
-#     Compile without SDL_Mixer, add 'NOMIXER=1'
-#     Compile without SDL_Mixer_X, add 'NOMIXERX=1' (Win32 only)
-#     Compile without GME, add 'NOGME=1'
-#     Compile without BSD API, add 'NONET=1'
-#     Compile without IPX/SPX, add 'NOIPX=1'
-#     Compile Mingw/SDL with S_DS3S, add 'DS3D=1'
-#     Compile without libopenmpt, add 'NOOPENMPT=1'
-#     Compile with S_FMOD3D, add 'FMOD=1' (WIP)
-#     Compile with S_OPENAL, add 'OPENAL=1' (WIP)
-#     To link with the whole SDL_Image lib to load Icons, add 'SDL_IMAGE=1' but it isn't not realy needed
-#     To link with SDLMain to hide console or make on a console-less binary, add 'SDLMAIN=1'
+# LINUX=1, LINUX64=1
+# MINGW=1, MINGW64=1 - Windows (MinGW toolchain)
+# UNIX=1 - Generic Unix like system
+# FREEBSD=1
+# SDL=1 - Use SDL backend. SDL is the only backend though
+#         and thus, always enabled.
 #
-#############################################################################
-
-,=,
-
-ifeq (,$(filter-out cleandep clean distclean,$(or $(MAKECMDGOALS),all)))
-CLEANONLY=1
-else ifndef SILENT
-echo=@echo "$(1)"
-ifndef MAKE_RESTARTS
-print=$(info $(1))
-endif
-endif
-
-ALL_SYSTEMS=\
-	PANDORA\
-	LINUX64\
-	MINGW64\
-	HAIKU\
-	DUMMY\
-	DJGPPDOS\
-	MINGW\
-	UNIX\
-	LINUX\
-	SOLARIS\
-	FREEBSD\
-	MACOSX\
-	SDL\
-
-# check for user specified system
-ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES)))
-ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
-
- $(call print,Detected a Windows system$(,) compiling for 32-bit MinGW SDL2...)
-
- # go for a 32-bit sdl mingw exe by default
- MINGW=1
- WINDOWSHELL=1
-
-else # if you on the *nix
-
- system:=$(shell uname -s)
-
- ifeq ($(system),Linux)
- new_system=LINUX
- else
-
- $(error \
-	 Could not automatically detect your system,\
-	 try specifying a system manually)
-
- endif
-
- ifeq ($(shell getconf LONG_BIT),64)
- system+=64-bit
- new_system:=$(new_system)64
- endif
-
- $(call print,Detected $(system) ($(new_system))...)
- $(new_system)=1
-
-endif
-endif
-
-
-# SRB2 data files
-D_DIR?=../bin/Resources
-D_FILES=$(D_DIR)/srb2.pk3 \
-	$(D_DIR)/player.dta \
-	$(D_DIR)/zones.pk3 \
-	$(D_DIR)/music.dta \
-
-PKG_CONFIG?=pkg-config
-
-ifdef PANDORA
-LINUX=1
-endif
-
-ifdef LINUX64
-LINUX=1
-NONX86=1
-# LINUX64 does not imply X86_64=1; could mean ARM64 or Itanium
-endif
-
-ifdef MINGW64
-MINGW=1
-NONX86=1
-NOASM=1
-# MINGW64 should not necessarily imply X86_64=1, but we make that assumption elsewhere
-# Once that changes, remove this
-X86_64=1
-endif #ifdef MINGW64
-
-ifdef HAIKU
-SDL=1
-endif
-
-include Makefile.cfg
-
-ifdef DUMMY
-NOPNG=1
-NOZLIB=1
-NONET=1
-NOHW=1
-NOASM=1
-NOIPX=1
-EXENAME?=srb2dummy
-OBJS=$(OBJDIR)/i_video.o
-LIBS=-lm
-endif
+# A list of supported GCC versions can be found in
+# Makefile.d/detect.mk -- search 'gcc_versions'.
+#
+# Feature flags:
+#
+# Safe to use online
+# ------------------
+# NO_IPV6=1 - Disable IPv6 address support.
+# NOHW=1 - Disable OpenGL renderer.
+# ZDEBUG=1 - Enable more detailed memory debugging
+# HAVE_MINIUPNPC=1 - Enable automated port forwarding.
+#                    Already enabled by default for 32-bit
+#                    Windows.
+# NOASM=1 - Disable hand optimized assembly code for the
+#           Software renderer.
+# NOPNG=1 - Disable PNG graphics support. (TODO: double
+#           check netplay compatible.)
+# NOCURL=1 - Disable libcurl--HTTP capability.
+# NOGME=1 - Disable game music emu, retro VGM support.
+# NOOPENMPT=1 - Disable module (tracker) music support.
+# NOMIXER=1 - Disable SDL Mixer (audio playback).
+# NOMIXERX=1 - Forgo SDL Mixer X--revert to standard SDL
+#              Mixer. Mixer X is the default for Windows
+#              builds.
+# HAVE_MIXERX=1 - Enable SDL Mixer X. Outside of Windows
+#                 builds, SDL Mixer X is not the default.
+# NOTHREADS=1 - Disable multithreading.
+#
+# Netplay incompatible
+# --------------------
+# NONET=1 - Disable online capability.
+# NOMD5=1 - Disable MD5 checksum (validation tool).
+# NOPOSTPROCESSING=1 - ?
+# MOBJCONSISTANCY=1 - ??
+# PACKETDROP=1 - ??
+# DEBUGMODE=1 - Enable various debugging capabilities.
+#               Also disables optimizations.
+# NOZLIB=1 - Disable some compression capability. Implies
+#            NOPNG=1.
+#
+# Development flags:
+#
+# VALGRIND=1 - Enable Valgrind memory debugging support.
+# PROFILEMODE=1 - Enable performance profiling (gprof).
+#
+# General flags for building:
+#
+# STATIC=1 - Use static linking.
+# DISTCC=1
+# CCACHE=1
+# NOOBJDUMP=1 - Don't disassemble executable.
+# NOUPX=1 - Don't compress executable.
+# WINDOWSHELL=1 - Use Windows commands.
+# PREFIX= - Prefix to many commands, for cross compiling.
+# YASM=1 - Use Yasm instead of NASM assembler.
+# STABS=1 - ?
+# ECHO=1 - Print out each command in the build process.
+# NOECHOFILENAMES=1 - Don't print out each that is being
+#                     worked on.
+# SILENT=1 - Print absolutely nothing except errors.
+# RELAXWARNINGS=1 - Use less compiler warnings/errors.
+# ERRORMODE=1 - Treat most compiler warnings as errors.
+# NOCASTALIGNWARN=1 - ?
+# NOLDWARNING=1 - ?
+# NOSDLMAIN=1 - ?
+# SDLMAIN=1 - ?
+#
+# Library configuration flags:
+# Everything here is an override.
+#
+# PNG_PKGCONFIG= - libpng-config command.
+# PNG_CFLAGS=, PNG_LDFLAGS=
+#
+# CURLCONFIG= - curl-config command.
+# CURL_CFLAGS=, CURL_LDFLAGS=
+#
+# VALGRIND_PKGCONFIG= - pkg-config package name.
+# VALGRIND_CFLAGS=, VALGRIND_LDFLAGS=
+#
+# LIBGME_PKGCONFIG=, LIBGME_CFLAGS=, LIBGME_LDFLAGS=
 
-ifdef HAIKU
-NOIPX=1
-NOASM=1
-ifndef NONET
-LIBS=-lnetwork
-endif
-CFLAGS+=-DUNIXCOMMON
-PNG_CFLAGS?=
-PNG_LDFLAGS?=-lpng
-endif
+# LIBOPENMPT_PKGCONFIG=
+# LIBOPENMPT_CFLAGS=, LIBOPENMPT_LDFLAGS=
+#
+# ZLIB_PKGCONFIG=, ZLIB_CFLAGS=, ZLIB_LDFLAGS=
+#
+# SDL_PKGCONFIG=
+# SDL_CONFIG= - sdl-config command.
+# SDL_CFLAGS=, SDL_LDFLAGS=
 
-ifdef PANDORA
-NONX86=1
-NOHW=1
-endif
+clean_targets=cleandep clean distclean info
 
-ifndef NOOPENMPT
-HAVE_OPENMPT=1
-endif
+.PHONY : $(clean_targets) all
 
-ifdef MINGW
-include win32/Makefile.cfg
-endif #ifdef MINGW
+goals:=$(or $(MAKECMDGOALS),all)
+cleanonly:=$(filter $(clean_targets),$(goals))
+destructive:=$(filter-out info,$(cleanonly))
 
-ifdef UNIX
-UNIXCOMMON=1
-endif
+include Makefile.d/util.mk
 
-ifdef LINUX
-UNIXCOMMON=1
-ifndef NOGME
-HAVE_LIBGME=1
-endif
+ifdef PREFIX
+CC:=$(PREFIX)-gcc
 endif
 
-ifdef SOLARIS
-UNIXCOMMON=1
-endif
+OBJDUMP_OPTS?=--wide --source --line-numbers
 
-ifdef FREEBSD
-UNIXCOMMON=1
-endif
+OBJCOPY:=$(call Prefix,objcopy)
+OBJDUMP:=$(call Prefix,objdump) $(OBJDUMP_OPTS)
+WINDRES:=$(call Prefix,windres)
 
-ifdef MACOSX
-UNIXCOMMON=1
+ifdef YASM
+NASM?=yasm
+else
+NASM?=nasm
 endif
 
-ifdef SDL
-	include sdl/Makefile.cfg
-endif #ifdef SDL
-
-ifdef DISTCC
-        CC:=distcc $(CC)
+ifdef YASM
+ifdef STABS
+NASMOPTS?=-g stabs
+else
+NASMOPTS?=-g dwarf2
 endif
-
-ifdef CCACHE
-        CC:=ccache $(CC)
+else
+NASMOPTS?=-g
 endif
 
-MSGFMT?=msgfmt
-
+GZIP?=gzip
+GZIP_OPTS?=-9 -f -n
 ifdef WINDOWSHELL
-	COMPTIME=-..\comptime.bat
-else
-	COMPTIME=-../comptime.sh
+GZIP_OPTS+=--rsyncable
 endif
 
+UPX?=upx
+UPX_OPTS?=--best --preserve-build-id
 ifndef ECHO
-	NASM:=@$(NASM)
-	REMOVE:=@$(REMOVE)
-	CC:=@$(CC)
-	CXX:=@$(CXX)
-	OBJCOPY:=@$(OBJCOPY)
-	OBJDUMP:=@$(OBJDUMP)
-	STRIP:=@$(STRIP)
-	WINDRES:=@$(WINDRES)
-	MKDIR:=@$(MKDIR)
-	GZIP:=@$(GZIP)
-	MSGFMT:=@$(MSGFMT)
-	UPX:=@$(UPX)
-	UPX_OPTS+=-q
-	COMPTIME:=@$(COMPTIME)
-endif
-
-ifdef NONET
-	OPTS+=-DNONET
-	NOCURL=1
-else
-ifdef NO_IPV6
-	OPTS+=-DNO_IPV6
-endif
+UPX_OPTS+=-qq
 endif
 
-ifdef NOHW
-	OPTS+=-DNOHW
-else
-	OPTS+=-DHWRENDER
-	OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
-		 $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o \
-		 $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
-endif
+include Makefile.d/detect.mk
 
-OPTS += -DCOMPVERSION
+# make would try to remove the implicitly made directories
+.PRECIOUS : %/ comptime.c
 
-ifndef NONX86
-ifndef GCC29
-	ARCHOPTS?=-msse3 -mfpmath=sse
-else
-	ARCHOPTS?=-mpentium
-endif
-else
-ifdef X86_64
-	ARCHOPTS?=-march=nocona
-endif
-endif
+# very sophisticated dependency
+sources:=\
+	$(call List,Sourcefile)\
+	$(call List,blua/Sourcefile)\
 
-ifndef NOASM
-ifndef NONX86
-	OBJS+=$(OBJDIR)/tmap.o $(OBJDIR)/tmap_mmx.o
-	OPTS+=-DUSEASM
-endif
-endif
+makedir:=../make
 
-ifndef NOPNG
-OPTS+=-DHAVE_PNG
+# -DCOMPVERSION: flag to use comptime.h
+opts:=-DCOMPVERSION -g
+libs:=
 
-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
-else
-PNG_CONFIG?=libpng-config
-endif
+nasm_format:=
 
-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
+# This is a list of variables names, of which if defined,
+# also defines the name as a macro to the compiler.
+passthru_opts:=
 
-ifdef LINUX
-PNG_CFLAGS+=-D_LARGEFILE64_SOURCE
-endif
+include Makefile.d/platform.mk
+include Makefile.d/features.mk
+include Makefile.d/versions.mk
 
-LIBS+=$(PNG_LDFLAGS)
-CFLAGS+=$(PNG_CFLAGS)
-
-OBJS+=$(OBJDIR)/apng.o
+ifdef DEBUGMODE
+makedir:=$(makedir)/debug
 endif
 
-ifdef HAVE_LIBGME
-OPTS+=-DHAVE_LIBGME
+depdir:=$(makedir)/deps
+objdir:=$(makedir)/objs
 
-LIBGME_PKGCONFIG?=libgme
-LIBGME_CFLAGS?=$(shell $(PKG_CONFIG) $(LIBGME_PKGCONFIG) --cflags)
-LIBGME_LDFLAGS?=$(shell $(PKG_CONFIG) $(LIBGME_PKGCONFIG) --libs)
+depends:=$(basename $(filter %.c %.s,$(sources)))
+objects:=$(basename $(filter %.c %.s %.nas,$(sources)))
 
-LIBS+=$(LIBGME_LDFLAGS)
-CFLAGS+=$(LIBGME_CFLAGS)
-endif
+depends:=$(depends:%=$(depdir)/%.d)
 
-ifdef HAVE_OPENMPT
-OPTS+=-DHAVE_OPENMPT
+# 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
 
-LIBOPENMPT_PKGCONFIG?=libopenmpt
-LIBOPENMPT_CFLAGS?=$(shell $(PKG_CONFIG) $(LIBOPENMPT_PKGCONFIG) --cflags)
-LIBOPENMPT_LDFLAGS?=$(shell $(PKG_CONFIG) $(LIBOPENMPT_PKGCONFIG) --libs)
-
-LIBS+=$(LIBOPENMPT_LDFLAGS)
-CFLAGS+=$(LIBOPENMPT_CFLAGS)
+# windows resource file
+rc_file:=$(basename $(filter %.rc,$(sources)))
+ifdef rc_file
+objects+=$(rc_file:=.res)
 endif
 
-ifndef NOZLIB
-OPTS+=-DHAVE_ZLIB
-ZLIB_PKGCONFIG?=zlib
-ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags)
-ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs)
+objects:=$(addprefix $(objdir)/,$(objects))
 
-LIBS+=$(ZLIB_LDFLAGS)
-CFLAGS+=$(ZLIB_CFLAGS)
+ifdef DEBUGMODE
+bin:=../bin/debug
 else
-NOPNG=1
+bin:=../bin
 endif
 
-ifndef NOCURL
-OPTS+=-DHAVE_CURL
-CURLCONFIG?=curl-config
-CURL_CFLAGS?=$(shell $(CURLCONFIG) --cflags)
-CURL_LDFLAGS?=$(shell $(CURLCONFIG) --libs)
-
-LIBS+=$(CURL_LDFLAGS)
-CFLAGS+=$(CURL_CFLAGS)
-endif
+# default EXENAME (usually set by platform)
+EXENAME?=srb2
+DBGNAME?=$(EXENAME).debug
 
-ifdef STATIC
-LIBS:=-static $(LIBS)
-endif
+exe:=$(bin)/$(EXENAME)
+dbg:=$(bin)/$(DBGNAME)
 
-ifdef HAVE_MINIUPNPC
-ifdef NONET
-HAVE_MINIUPNPC=''
-else
-LIBS+=-lminiupnpc
-ifdef MINGW
-LIBS+=-lws2_32 -liphlpapi
-endif
-CFLAGS+=-DHAVE_MINIUPNPC
-endif
-endif
+build_done=Build is done, please look for $(<F) in $(<D)
 
-include blua/Makefile.cfg
+all : $(exe)
+	$(call Echo,$(build_done))
 
-ifdef NOMD5
-	OPTS+=-DNOMD5
-else
-	OBJS:=$(OBJDIR)/md5.o $(OBJS)
+ifndef VALGRIND
+ifndef NOOBJDUMP
+all : $(dbg).txt
 endif
-
-ifdef NOPOSTPROCESSING
-	OPTS+=-DNOPOSTPROCESSING
 endif
 
-	OPTS:=-fno-exceptions $(OPTS)
-
-ifdef MOBJCONSISTANCY
-	OPTS+=-DMOBJCONSISTANCY
+ifdef STATIC
+libs+=-static
 endif
 
-ifdef PACKETDROP
-	OPTS+=-DPACKETDROP
+# build with profiling information
+ifdef PROFILEMODE
+opts+=-pg
+libs+=-pg
 endif
 
 ifdef DEBUGMODE
-
-	# build with debugging information
-	WINDRESFLAGS = -D_DEBUG
-ifdef GCC48
-	CFLAGS+=-Og
-else
-	CFLAGS+=-O0
+debug_opts=-D_DEBUG
+else # build a normal optimized version
+debug_opts=-DNDEBUG
+opts+=-O3
 endif
-	CFLAGS+= -Wall -DPARANOIA -DRANGECHECK -DPACKETDROP -DMOBJCONSISTANCY
-else
 
+# debug_opts also get passed to windres
+opts+=$(debug_opts)
 
-	# build a normal optimised version
-	WINDRESFLAGS = -DNDEBUG
-	CFLAGS+=-O3
-endif
-	CFLAGS+=-g $(OPTS) $(ARCHOPTS) $(WINDRESFLAGS)
+opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v)))
 
-ifdef YASM
-ifdef STABS
-	NASMOPTS?= -g stabs
-else
-	NASMOPTS?= -g dwarf2
-endif
-else
-	NASMOPTS?= -g
-endif
+CFLAGS:=$(opts) $(WFLAGS) $(CPPFLAGS) $(CFLAGS)
+LDFLAGS:=$(libs) $(LDFLAGS)
+ASFLAGS+=-x assembler-with-cpp
 
-ifdef PROFILEMODE
-	# build with profiling information
-	CFLAGS+=-pg
-	LDFLAGS+=-pg
+ifdef DISTCC
+CC:=distcc $(CC)
 endif
 
-ifdef ZDEBUG
-	CPPFLAGS+=-DZDEBUG
+ifdef CCACHE
+CC:=ccache $(CC)
 endif
 
-OPTS+=$(CPPFLAGS)
-
-# default EXENAME if all else fails
-EXENAME?=srb2
-DBGNAME?=$(EXENAME).debug
-
-# $(OBJDIR)/dstrings.o \
-
-# not too sophisticated dependency
-OBJS:=$(i_main_o) \
-		$(OBJDIR)/string.o   \
-		$(OBJDIR)/d_main.o   \
-		$(OBJDIR)/d_clisrv.o \
-		$(OBJDIR)/d_net.o    \
-		$(OBJDIR)/d_netfil.o \
-		$(OBJDIR)/d_netcmd.o \
-		$(OBJDIR)/dehacked.o \
-		$(OBJDIR)/z_zone.o   \
-		$(OBJDIR)/f_finale.o \
-		$(OBJDIR)/f_wipe.o   \
-		$(OBJDIR)/g_demo.o   \
-		$(OBJDIR)/g_game.o   \
-		$(OBJDIR)/g_input.o  \
-		$(OBJDIR)/am_map.o   \
-		$(OBJDIR)/command.o  \
-		$(OBJDIR)/console.o  \
-		$(OBJDIR)/hu_stuff.o \
-		$(OBJDIR)/y_inter.o  \
-		$(OBJDIR)/st_stuff.o \
-		$(OBJDIR)/m_aatree.o \
-		$(OBJDIR)/m_anigif.o \
-		$(OBJDIR)/m_argv.o   \
-		$(OBJDIR)/m_bbox.o   \
-		$(OBJDIR)/m_cheat.o  \
-		$(OBJDIR)/m_cond.o   \
-		$(OBJDIR)/m_fixed.o  \
-		$(OBJDIR)/m_menu.o   \
-		$(OBJDIR)/m_misc.o   \
-		$(OBJDIR)/m_random.o \
-		$(OBJDIR)/m_queue.o  \
-		$(OBJDIR)/info.o     \
-		$(OBJDIR)/p_ceilng.o \
-		$(OBJDIR)/p_enemy.o  \
-		$(OBJDIR)/p_floor.o  \
-		$(OBJDIR)/p_inter.o  \
-		$(OBJDIR)/p_lights.o \
-		$(OBJDIR)/p_map.o    \
-		$(OBJDIR)/p_maputl.o \
-		$(OBJDIR)/p_mobj.o   \
-		$(OBJDIR)/p_polyobj.o\
-		$(OBJDIR)/p_saveg.o  \
-		$(OBJDIR)/p_setup.o  \
-		$(OBJDIR)/p_sight.o  \
-		$(OBJDIR)/p_spec.o   \
-		$(OBJDIR)/p_telept.o \
-		$(OBJDIR)/p_tick.o   \
-		$(OBJDIR)/p_user.o   \
-		$(OBJDIR)/p_slopes.o \
-		$(OBJDIR)/tables.o   \
-		$(OBJDIR)/r_bsp.o    \
-		$(OBJDIR)/r_data.o   \
-		$(OBJDIR)/r_draw.o   \
-		$(OBJDIR)/r_main.o   \
-		$(OBJDIR)/r_plane.o  \
-		$(OBJDIR)/r_segs.o   \
-		$(OBJDIR)/r_skins.o  \
-		$(OBJDIR)/r_sky.o    \
-		$(OBJDIR)/r_splats.o \
-		$(OBJDIR)/r_things.o \
-		$(OBJDIR)/r_textures.o \
-		$(OBJDIR)/r_picformats.o \
-		$(OBJDIR)/r_portal.o \
-		$(OBJDIR)/screen.o   \
-		$(OBJDIR)/v_video.o  \
-		$(OBJDIR)/s_sound.o  \
-		$(OBJDIR)/sounds.o   \
-		$(OBJDIR)/w_wad.o    \
-		$(OBJDIR)/filesrch.o \
-		$(OBJDIR)/mserv.o    \
-		$(OBJDIR)/http-mserv.o\
-		$(OBJDIR)/i_tcp.o    \
-		$(OBJDIR)/lzf.o	     \
-		$(OBJDIR)/vid_copy.o \
-		$(OBJDIR)/b_bot.o \
-		$(i_net_o)      \
-		$(i_system_o)   \
-		$(i_sound_o)    \
-		$(OBJS)
-
-DEPS:=$(patsubst $(OBJDIR)/%.o,$(DEPDIR)/%.d,$(filter %.o,$(OBJS)))
-OBJS+=$(OBJDIR)/comptime.o
-
 ifndef SILENT
-ifndef ECHO
-ifndef NOECHOFILENAMES
-define echoName =
-	@echo -- $< ...
-endef
-endif
-endif
-endif
+# makefile will 'restart' when it finishes including the
+# dependencies.
+ifndef MAKE_RESTARTS
+ifndef destrutive
+$(shell $(CC) -v)
+define flags =
 
-# List of languages to compile.
-# For reference, this is the command I use to build a srb2.pot file from the source code.
-# (The listed source files are the ones containing translated strings).
-# FILES=""; for file in `find ./ | grep "\.c" | grep -v svn`; do [ "`grep "M_GetText(" $file`" ] && FILES="$FILES $file"; done; xgettext -d srb2 -o locale/srb2.pot -kM_GetText -F --no-wrap $FILES
-ifdef GETTEXT
-POS:=$(BIN)/en.mo
+CC ........ $(CC)
 
-OPTS+=-DGETTEXT
-endif
-
-ifdef PANDORA
-all: $(BIN)/$(PNDNAME)
-endif
+CFLAGS .... $(CFLAGS)
 
+LDFLAGS ... $(LDFLAGS)
 
-ifdef SDL
-all: $(BIN)/$(EXENAME)
+endef
+$(info $(flags))
 endif
-
-ifdef DUMMY
-all:	$(BIN)/$(EXENAME)
+# don't generate dependency files if only cleaning
+ifndef cleanonly
+$(info Checking dependency files...)
+include $(depends)
 endif
-
-cleandep:
-	$(REMOVE) $(DEPS)
-	$(REMOVE) comptime.h
-
-clean:
-	$(REMOVE) *~ *.flc
-	$(REMOVE) $(OBJDIR)/*.o
-
-distclean: clean cleandep
-
-ifdef MINGW
-	$(REMOVE) $(OBJDIR)/*.res
 endif
-
-ifdef CYGWIN32
-	$(REMOVE) $(OBJDIR)/*.res
 endif
 
-#make a big srb2.s that is the disasm of the exe (dos only ?)
-asm:
-	$(CC) $(LDFLAGS) $(OBJS) -o $(OBJDIR)/tmp.exe $(LIBS)
-	$(OBJDUMP) -d $(OBJDIR)/tmp.exe --no-show-raw-insn > srb2.s
-	$(REMOVE) $(OBJDIR)/tmp.exe
+LD:=$(CC)
+CC:=$(CC) $(CFLAGS)
+NASM:=$(NASM) $(NASMOPTS) -f $(nasm_format)
+GZIP:=$(GZIP) $(GZIP_OPTS)
+UPX:=$(UPX) $(UPX_OPTS)
+WINDRES:=$(WINDRES) $(WINDRESFLAGS)\
+	$(debug_opts) --include-dir=win32 -O coff
 
-# executable
-# NOTE: DJGPP's objcopy do not have --add-gnu-debuglink
+%/ :
+	$(.)$(mkdir) $@
 
-$(BIN)/$(EXENAME): $(POS) $(OBJS)
-	-$(MKDIR) $(BIN)
-	$(call echo,Linking $(EXENAME)...)
-	$(LD) $(LDFLAGS) $(OBJS) -o $(BIN)/$(EXENAME) $(LIBS)
-ifndef VALGRIND
-ifndef NOOBJDUMP
-	$(call echo,Dumping debugging info)
-	$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt
-ifdef WINDOWSHELL
-	-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
-else
-	-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
-endif
-endif
+# this is needed so the target can be referenced in the
+# prerequisites
+.SECONDEXPANSION :
 
-# 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
+# executable stripped of debugging symbols
+$(exe) : $(dbg) | $$(@D)/
+	$(.)$(OBJCOPY) --strip-debug $< $@
+	$(.)-$(OBJCOPY) --add-gnu-debuglink=$< $@
 ifndef NOUPX
-	-$(UPX) $(UPX_OPTS) $(BIN)/$(EXENAME)
-endif
+	$(call Echo,Compressing final executable...)
+	$(.)-$(UPX) $@
 endif
-	$(call echo,Build is done$(,) please look for $(EXENAME) in $(BIN)$(,) (checking for post steps))
 
-reobjdump:
-	$(call echo,Redumping debugging info)
-	$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt
-ifdef WINDOWSHELL
-	-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
-else
-	-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
-endif
+# original executable with debugging symbols
+$(dbg) : $(objects) | $$(@D)/
+	$(call Echo,Linking $(@F)...)
+	$(.)$(LD) -o $@ $^ $(LDFLAGS)
 
-$(OBJDIR):
-	-$(MKDIR) $(OBJDIR)
-
-ifdef SDL
-ifdef MINGW
-$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
- doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
- command.h hardware/hw_data.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
- hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
- am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
- p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-else
-$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
- doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
- command.h hardware/hw_data.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
- hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
- am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
- p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
-endif
-endif
+# disassembly of executable
+$(dbg).txt : $(dbg)
+	$(call Echo,Dumping debugging info...)
+	$(.)$(OBJDUMP) $< > $@
+	$(.)$(GZIP) $@
 
-#dependecy made by gcc itself !
-ifndef DUMMY
-ifndef CLEANONLY
-$(call print,Checking dependency files...)
--include $(DEPS)
-endif
+# '::' means run unconditionally
+# this really updates comptime.h
+comptime.c ::
+ifdef WINDOWSHELL
+	$(.)..\comptime.bat .
+else
+	$(.)../comptime.sh .
 endif
 
-undefine deps_rule
+# I wish I could make dependencies out of rc files :(
+$(objdir)/win32/Srb2win.res : \
+	win32/afxres.h win32/resource.h
 
-# windows makes it too hard !
+# dependency recipe template
+# 1: source file suffix
+# 2: extra flags to gcc
+define _recipe =
+$(depdir)/%.d : %.$(1) | $$$$(@D)/
 ifndef WINDOWSHELL
-ifdef echoName
-define deps_rule =
-	@printf "%-20.20s\r" $<
-
-endef
+ifdef Echo_name
+	@printf '%-20.20s\r' $$<
 endif
 endif
-
-define deps_rule +=
-	$(CC) $(CFLAGS) -M -MF $@ -MT $(OBJDIR)/$(<:.c=.o) $<
+	$(.)$(CC) -MM -MF $$@ -MT $(objdir)/$$(*F).o $(2) $$<
 endef
 
-$(DEPDIR)/%.d: %.c
-	$(deps_rule)
-
-$(DEPDIR)/%.d: $(INTERFACE)/%.c
-	$(deps_rule)
-
-$(DEPDIR)/%.d: hardware/%.c
-	$(deps_rule)
-
-$(DEPDIR)/%.d: blua/%.c
-	$(deps_rule)
-
-ifdef VALGRIND
-$(OBJDIR)/z_zone.o: z_zone.c
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@
-endif
-
-$(OBJDIR)/comptime.o::
-ifdef echoName
-	@echo -- comptime.c ...
-endif
-	$(COMPTIME) .
-	$(CC) $(CFLAGS) $(WFLAGS) -c comptime.c -o $@
-
-$(BIN)/%.mo: locale/%.po
-	-$(MKDIR) $(BIN)
-	$(echoName)
-	$(MSGFMT) -f -o $@ $<
-
-$(OBJDIR)/%.o: %.c
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(OBJDIR)/%.o: $(INTERFACE)/%.c
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-ifdef MACOSX
-$(OBJDIR)/%.o: sdl/macosx/%.c
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-endif
-
-$(OBJDIR)/%.o: hardware/%.c
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(OBJDIR)/%.o: blua/%.c
-	$(echoName)
-	$(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(OBJDIR)/%.o: %.nas
-	$(echoName)
-	$(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $<
-
-$(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc
-	$(echoName)
-	$(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@
-
-$(OBJDIR)/%.o: %.s
-	$(echoName)
-	$(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@
+$(eval $(call _recipe,c))
+$(eval $(call _recipe,s,$(ASFLAGS)))
+
+# 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
 
-$(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h
-	$(echoName)
-	$(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff
+$(eval $(call _recipe,o,c,$(CC) -c -o $$@ $$<))
+$(eval $(call _recipe,o,nas,$(NASM) -o $$@ $$<))
+$(eval $(call _recipe,o,s,$(CC) $(ASFLAGS) -c -o $$@ $$<))
+$(eval $(call _recipe,res,rc,$(WINDRES) -i $$< -o $$@))
 
+cleandep :
+	$(.)$(rmrf) $(depends) comptime.h
 
-ifdef SDL
+clean :
+	$(.)$(rmrf) $(exe) $(dbg) $(dbg).txt $(objects)
 
-ifdef MINGW
-$(OBJDIR)/win_dbg.o: win32/win_dbg.c
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-endif
+distclean :
+	$(.)$(rmrf) ../bin ../objs ../deps comptime.h
 
-ifdef STATICHS
-$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
- hardware/hw_dll.h
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
- hardware/hw_dll.h
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-
-ifdef MINGW
-$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \
- hardware/hw_dll.h
-	$(echoName)
-	$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
-endif
+info:
+ifdef WINDOWSHELL
+	@REM
 else
-
-$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
- hardware/hw_dll.h
-	$(echoName)
-	$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c
-
-$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
- hardware/hw_dll.h
-	$(echoName)
-	$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c
-endif
+	@:
 endif
-
-#############################################################
-#
-#############################################################
diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk
new file mode 100644
index 0000000000000000000000000000000000000000..f576bcf784ff17cbb2be112d5a622737f4214d05
--- /dev/null
+++ b/src/Makefile.d/detect.mk
@@ -0,0 +1,104 @@
+#
+# Detect the host system and compiler version.
+#
+
+# Previously featured:\
+	PANDORA\
+	HAIKU\
+	DUMMY\
+	DJGPPDOS\
+	SOLARIS\
+	MACOSX\
+
+all_systems:=\
+	LINUX64\
+	MINGW64\
+	MINGW\
+	UNIX\
+	LINUX\
+	FREEBSD\
+	SDL\
+
+# check for user specified system
+ifeq (,$(filter $(all_systems),$(.VARIABLES)))
+ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
+
+_m=Detected a Windows system,\
+	compiling for 32-bit MinGW SDL...)
+$(call Print,$(_m))
+
+# go for a 32-bit sdl mingw exe by default
+MINGW:=1
+WINDOWSHELL:=1
+
+else # if you on the *nix
+
+system:=$(shell uname -s)
+
+ifeq ($(system),Linux)
+new_system:=LINUX
+else
+
+$(error \
+	Could not automatically detect your system,\
+	try specifying a system manually)
+
+endif
+
+ifeq ($(shell getconf LONG_BIT),64)
+system+=64-bit
+new_system:=$(new_system)64
+endif
+
+$(call Print,Detected $(system) ($(new_system))...)
+$(new_system):=1
+
+endif
+endif
+
+# This must have high to low order.
+gcc_versions:=\
+	102 101\
+	93 92 91\
+	84 83 82 81\
+	75 74 73 72 71\
+	64 63 62 61\
+	55 54 53 52 51\
+	49 48 47 46 45 44 43 42 41 40
+
+latest_gcc_version:=10.2
+
+# Automatically set version flag, but not if one was
+# manually set. And don't bother if this is a clean only
+# run.
+ifeq (,$(call Wildvar,GCC% destructive))
+version:=$(shell $(CC) --version)
+
+# check if this is in fact GCC
+ifneq (,$(or $(findstring gcc,$(version)),\
+	$(findstring GCC,$(version))))
+
+version:=$(shell $(CC) -dumpversion)
+
+# Turn version into words of major, minor
+v:=$(subst ., ,$(version))
+# concat. major minor
+v:=$(word 1,$(v))$(word 2,$(v))
+
+# If this version is not in the list,
+# default to the latest supported
+ifeq (,$(filter $(v),$(gcc_versions)))
+define line =
+Your compiler version, GCC $(version), \
+is not supported by the Makefile.
+The Makefile will assume GCC $(latest_gcc_version).))
+endef
+$(call Print,$(line))
+GCC$(subst .,,$(latest_gcc_version)):=1
+else
+$(call Print,Detected GCC $(version) (GCC$(v)))
+GCC$(v):=1
+endif
+
+endif
+endif
diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk
new file mode 100644
index 0000000000000000000000000000000000000000..abdc342b7bb8c0f1ba06c5eca2027ad54b9b4642
--- /dev/null
+++ b/src/Makefile.d/features.mk
@@ -0,0 +1,76 @@
+#
+# Makefile for feature flags.
+#
+
+passthru_opts+=\
+	NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\
+	MOBJCONSISTANCY PACKETDROP ZDEBUG\
+	HAVE_MINIUPNPC\
+
+# build with debugging information
+ifdef DEBUGMODE
+MOBJCONSISTANCY=1
+PACKETDROP=1
+opts+=-DPARANOIA -DRANGECHECK
+endif
+
+ifndef NOHW
+opts+=-DHWRENDER
+sources+=$(call List,hardware/Sourcefile)
+endif
+
+ifndef NOASM
+ifndef NONX86
+sources+=tmap.nas tmap_mmx.nas
+opts+=-DUSEASM
+endif
+endif
+
+ifndef NOMD5
+sources+=md5.c
+endif
+
+ifndef NOZLIB
+ifndef NOPNG
+ifdef PNG_PKGCONFIG
+$(eval $(call Use_pkg_config,PNG_PKGCONFIG))
+else
+PNG_CONFIG?=$(call Prefix,libpng-config)
+$(eval $(call Configure,PNG,$(PNG_CONFIG) \
+	$(if $(PNG_STATIC),--static),,--ldflags))
+endif
+ifdef LINUX
+opts+=-D_LARGFILE64_SOURCE
+endif
+opts+=-DHAVE_PNG
+sources+=apng.c
+endif
+endif
+
+ifndef NONET
+ifndef NOCURL
+CURLCONFIG?=curl-config
+$(eval $(call Configure,CURL,$(CURLCONFIG)))
+opts+=-DHAVE_CURL
+endif
+endif
+
+ifdef HAVE_MINIUPNPC
+libs+=-lminiupnpc
+endif
+
+# (Valgrind is a memory debugger.)
+ifdef VALGRIND
+VALGRIND_PKGCONFIG?=valgrind
+$(eval $(call Use_pkg_config,VALGRIND))
+ZDEBUG=1
+opts+=-DHAVE_VALGRIND
+endif
+
+default_packages:=\
+	GME/libgme/LIBGME\
+	OPENMPT/libopenmpt/LIBOPENMPT\
+	ZLIB/zlib\
+
+$(foreach p,$(default_packages),\
+	$(eval $(call Check_pkg_config,$(p))))
diff --git a/src/Makefile.d/lua.mk b/src/Makefile.d/lua.mk
deleted file mode 100644
index 12ea064b417fc60ad14fd1a3520d6b0280b6fce8..0000000000000000000000000000000000000000
--- a/src/Makefile.d/lua.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-ifdef UNIXCOMMON
-LUA_CFLAGS+=-DLUA_USE_POSIX
-endif
-ifdef LINUX
-LUA_CFLAGS+=-DLUA_USE_POSIX
-endif
-ifdef GCC43
-ifndef GCC44
-WFLAGS+=-Wno-logical-op
-endif
-endif
-
-OBJS:=$(OBJS) \
-	$(OBJDIR)/lapi.o \
-	$(OBJDIR)/lbaselib.o \
-	$(OBJDIR)/ldo.o \
-	$(OBJDIR)/lfunc.o \
-	$(OBJDIR)/linit.o \
-	$(OBJDIR)/liolib.o \
-	$(OBJDIR)/llex.o \
-	$(OBJDIR)/lmem.o \
-	$(OBJDIR)/lobject.o \
-	$(OBJDIR)/lstate.o \
-	$(OBJDIR)/lstrlib.o \
-	$(OBJDIR)/ltablib.o \
-	$(OBJDIR)/lundump.o \
-	$(OBJDIR)/lzio.o \
-	$(OBJDIR)/lauxlib.o \
-	$(OBJDIR)/lcode.o \
-	$(OBJDIR)/ldebug.o \
-	$(OBJDIR)/ldump.o \
-	$(OBJDIR)/lgc.o \
-	$(OBJDIR)/lopcodes.o \
-	$(OBJDIR)/lparser.o \
-	$(OBJDIR)/lstring.o \
-	$(OBJDIR)/ltable.o \
-	$(OBJDIR)/ltm.o \
-	$(OBJDIR)/lvm.o \
-	$(OBJDIR)/lua_script.o \
-	$(OBJDIR)/lua_baselib.o \
-	$(OBJDIR)/lua_mathlib.o \
-	$(OBJDIR)/lua_hooklib.o \
-	$(OBJDIR)/lua_consolelib.o \
-	$(OBJDIR)/lua_infolib.o \
-	$(OBJDIR)/lua_mobjlib.o \
-	$(OBJDIR)/lua_playerlib.o \
-	$(OBJDIR)/lua_skinlib.o \
-	$(OBJDIR)/lua_thinkerlib.o \
-	$(OBJDIR)/lua_maplib.o \
-	$(OBJDIR)/lua_blockmaplib.o \
-	$(OBJDIR)/lua_hudlib.o
diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk
index 47c944eb5f21e8451c55374b212220fa09072360..fdcd40d4d4d62be470e41009605058f7aca00842 100644
--- a/src/Makefile.d/nix.mk
+++ b/src/Makefile.d/nix.mk
@@ -1,74 +1,40 @@
 #
-# sdl/makeNIX.cfg for SRB2/?nix
+# Makefile options for unices (linux, bsd...)
 #
 
-#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
+EXENAME?=lsdl2srb2
 
-	#LDFLAGS = -L/usr/local/lib
-	LIBS=-lm
-ifdef LINUX
-	LIBS+=-lrt
-ifdef NOTERMIOS
-	OPTS+=-DNOTERMIOS
-endif
-endif
+opts+=-DUNIXCOMMON -DLUA_USE_POSIX
+libs+=-lm
 
-ifdef LINUX64
-	OPTS+=-DLINUX64
+ifndef nasm_format
+nasm_format:=elf -DLINUX
 endif
 
-#
-#here is Solaris
-#
-ifdef SOLARIS
-	NOIPX=1
-	NOASM=1
-	OPTS+=-DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP
-	OPTS+=-I/usr/local/include -I/opt/sfw/include
-	LDFLAGS+=-L/opt/sfw/lib
-	LIBS+=-lsocket -lnsl
-endif
-
-#
-#here is FreeBSD
-#
-ifdef FREEBSD
-	OPTS+=-DLINUX -DFREEBSD -I/usr/X11R6/include
-	SDL_CONFIG?=sdl11-config
-	LDFLAGS+=-L/usr/X11R6/lib
-	LIBS+=-lipx -lkvm
+ifndef NOHW
+opts+=-I/usr/X11R6/include
+libs+=-L/usr/X11R6/lib
 endif
 
-#
-#here is Mac OS X
-#
-ifdef MACOSX
-	OBJS+=$(OBJDIR)/mac_resources.o
-	OBJS+=$(OBJDIR)/mac_alert.o
-	LIBS+=-framework CoreFoundation
-endif
+SDL=1
 
-ifndef NOHW
-	OPTS+=-I/usr/X11R6/include
-	LDFLAGS+=-L/usr/X11R6/lib
+# In common usage.
+ifdef LINUX
+libs+=-lrt
+passthru_opts+=NOTERMIOS
 endif
 
-	# name of the exefile
-	EXENAME?=lsdl2srb2
+# Tested by Steel, as of release 2.2.8.
+ifdef FREEBSD
+opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD
+libs+=-L/usr/X11R6/lib -lipx -lkvm
+endif
+
+# FIXME
+#ifdef SOLARIS
+#NOIPX=1
+#NOASM=1
+#opts+=-I/usr/local/include -I/opt/sfw/include \
+#		-DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP
+#libs+=-L/opt/sfw/lib -lsocket -lnsl
+#endif
diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk
new file mode 100644
index 0000000000000000000000000000000000000000..ca00806d9d5ddd676f6e1a8866149547cb82acef
--- /dev/null
+++ b/src/Makefile.d/platform.mk
@@ -0,0 +1,67 @@
+#
+# Platform specific options.
+#
+
+PKG_CONFIG?=pkg-config
+
+ifdef WINDOWSHELL
+rmrf?=DEL /S /Q
+mkdir?=MD
+else
+rmrf?=rm -rf
+mkdir?=mkdir -p
+endif
+
+ifdef LINUX64
+LINUX=1
+endif
+
+ifdef MINGW64
+MINGW=1
+endif
+
+ifdef LINUX
+UNIX=1
+ifdef LINUX64
+NONX86=1
+# LINUX64 does not imply X86_64=1;
+# could mean ARM64 or Itanium
+platform=linux/64
+else
+platform=linux
+endif
+else ifdef FREEBSD
+UNIX=1
+platform=freebsd
+else ifdef SOLARIS # FIXME
+UNIX=1
+platform=solaris
+else ifdef CYGWIN32 # FIXME
+nasm_format=win32
+platform=cygwin
+else ifdef MINGW
+ifdef MINGW64
+NONX86=1
+NOASM=1
+# MINGW64 should not necessarily imply X86_64=1,
+# but we make that assumption elsewhere
+# Once that changes, remove this
+X86_64=1
+platform=mingw
+else
+platform=mingw/64
+endif
+include Makefile.d/win32.mk
+endif
+
+ifdef platform
+makedir:=$(makedir)/$(platform)
+endif
+
+ifdef UNIX
+include Makefile.d/nix.mk
+endif
+
+ifdef SDL
+include Makefile.d/sdl.mk
+endif
diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk
index 45d0d6ba75a666cba5e4e2c3a3f9704987705cb6..43a2ffcedc9f58c174f2b5f60c817b0b23e70007 100644
--- a/src/Makefile.d/sdl.mk
+++ b/src/Makefile.d/sdl.mk
@@ -1,125 +1,98 @@
 #
-# sdl/makefile.cfg for SRB2/SDL
+# Makefile options for SDL2 backend.
 #
 
 #
-#SDL...., *looks at Alam*, THIS IS A MESS!
+# SDL...., *looks at Alam*, THIS IS A MESS!
+# 
+# ...a little bird flexes its muscles...
 #
 
-ifdef UNIXCOMMON
-include sdl/MakeNIX.cfg
-endif
+makedir:=$(makedir)/SDL
 
-ifdef PANDORA
-include sdl/SRB2Pandora/Makefile.cfg
-endif #ifdef PANDORA
+sources+=$(call List,sdl/Sourcefile)
+opts+=-DDIRECTFULLSCREEN -DHAVE_SDL
 
-ifdef CYGWIN32
-include sdl/MakeCYG.cfg
-endif #ifdef CYGWIN32
+# FIXME
+#ifdef PANDORA
+#include sdl/SRB2Pandora/Makefile.cfg
+#endif #ifdef PANDORA
 
-ifdef SDL_PKGCONFIG
-SDL_CFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --cflags)
-SDL_LDFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --libs)
-else
-ifdef PREFIX
-	SDL_CONFIG?=$(PREFIX)-sdl2-config
-else
-	SDL_CONFIG?=sdl2-config
-endif
-
-ifdef STATIC
-	SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags)
-	SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --static-libs)
-else
-	SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags)
-	SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --libs)
-endif
-endif
-
-
-	#use the x86 asm code
-ifndef CYGWIN32
-ifndef NOASM
-	USEASM=1
-endif
-endif
-
-	OBJS+=$(OBJDIR)/i_video.o $(OBJDIR)/dosstr.o $(OBJDIR)/endtxt.o $(OBJDIR)/hwsym_sdl.o
-
-	OPTS+=-DDIRECTFULLSCREEN -DHAVE_SDL
+# FIXME
+#ifdef CYGWIN32
+#include sdl/MakeCYG.cfg
+#endif #ifdef CYGWIN32
 
 ifndef NOHW
-	OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/ogl_sdl.o
+sources+=sdl/ogl_sdl.c
 endif
 
 ifdef NOMIXER
-	i_sound_o=$(OBJDIR)/sdl_sound.o
-else
-	i_sound_o=$(OBJDIR)/mixer_sound.o
-	OPTS+=-DHAVE_MIXER
-ifdef HAVE_MIXERX
-	OPTS+=-DHAVE_MIXERX
-	SDL_LDFLAGS+=-lSDL2_mixer_ext
+sources+=sdl/sdl_sound.c
 else
-	SDL_LDFLAGS+=-lSDL2_mixer
-endif
+opts+=-DHAVE_MIXER
+sources+=sdl/mixer_sound.c
+
+  ifdef HAVE_MIXERX
+  opts+=-DHAVE_MIXERX
+  libs+=-lSDL2_mixer_ext
+  else
+  libs+=-lSDL2_mixer
+  endif
 endif
 
 ifndef NOTHREADS
-	OPTS+=-DHAVE_THREADS
-	OBJS+=$(OBJDIR)/i_threads.o
+opts+=-DHAVE_THREADS
+sources+=sdl/i_threads.c
 endif
 
-ifdef SDL_TTF
-	OPTS+=-DHAVE_TTF
-	SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz
-	OBJS+=$(OBJDIR)/i_ttf.o
+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 SDL_IMAGE
-	OPTS+=-DHAVE_IMAGE
-	SDL_LDFLAGS+=-lSDL2_image
+# use the x86 asm code
+ifndef CYGWIN32
+ifndef NOASM
+USEASM=1
 endif
-
-ifdef SDL_NET
-	OPTS+=-DHAVE_SDLNET
-	SDL_LDFLAGS+=-lSDL2_net
 endif
 
+# FIXME
+#ifdef SDL_TTF
+#	OPTS+=-DHAVE_TTF
+#	SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz
+#	OBJS+=$(OBJDIR)/i_ttf.o
+#endif
+
+# FIXME
+#ifdef SDL_IMAGE
+#	OPTS+=-DHAVE_IMAGE
+#	SDL_LDFLAGS+=-lSDL2_image
+#endif
+
+# FIXME
+#ifdef SDL_NET
+#	OPTS+=-DHAVE_SDLNET
+#	SDL_LDFLAGS+=-lSDL2_net
+#endif
+
 ifdef MINGW
 ifndef NOSDLMAIN
-	SDLMAIN=1
+SDLMAIN=1
 endif
 endif
 
 ifdef SDLMAIN
-	OPTS+=-DSDLMAIN
-else
-ifdef MINGW
-	SDL_CFLAGS+=-Umain
-	SDL_LDFLAGS+=-mconsole
-endif
-endif
-
-ifndef NOHW
-ifdef OPENAL
-ifdef MINGW
-	LIBS:=-lopenal32 $(LIBS)
-else
-	LIBS:=-lopenal $(LIBS)
-endif
+opts+=-DSDLMAIN
 else
 ifdef MINGW
-ifdef DS3D
-	LIBS:=-ldsound -luuid $(LIBS)
-endif
-endif
+opts+=-Umain
+libs+=-mconsole
 endif
 endif
-
-CFLAGS+=$(SDL_CFLAGS)
-LIBS:=$(SDL_LDFLAGS) $(LIBS)
-ifdef STATIC
-	LIBS+=$(shell $(SDL_CONFIG) --static-libs)
-endif
diff --git a/src/Makefile.d/util.mk b/src/Makefile.d/util.mk
new file mode 100644
index 0000000000000000000000000000000000000000..88f141bee96b38eb2dc41e355fc3f666420cdbe8
--- /dev/null
+++ b/src/Makefile.d/util.mk
@@ -0,0 +1,89 @@
+#
+# 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.
+List=$(addprefix $(dir $(1)),$(file < $(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
index 075cd2d3a8defa3fd7d11feb431d2ad9cc67a704..fe2b6b851a20a7881a5298dce975fcb886f09664 100644
--- a/src/Makefile.d/versions.mk
+++ b/src/Makefile.d/versions.mk
@@ -1,215 +1,23 @@
-# vim: ft=make
 #
-# Makefile.cfg for SRB2
+# Flags to put a sock in GCC!
 #
 
-#
-# GNU compiler & tools' flags
-# and other things
-#
-
-# See the following variable don't start with 'GCC'. This is
-# to avoid a false positive with the version detection...
-
-SUPPORTED_GCC_VERSIONS:=\
-	101 102\
-	91 92 93\
-	81 82 83 84\
-	71 72 73 74 75\
-	61 62 63 64\
-	51 52 53 54 55\
-	40 41 42 43 44 45 46 47 48 49
-
-LATEST_GCC_VERSION=10.2
-
-# gcc or g++
-ifdef PREFIX
-	CC=$(PREFIX)-gcc
-	CXX=$(PREFIX)-g++
-	OBJCOPY=$(PREFIX)-objcopy
-	OBJDUMP=$(PREFIX)-objdump
-	STRIP=$(PREFIX)-strip
-	WINDRES=$(PREFIX)-windres
-else
-	OBJCOPY=objcopy
-	OBJDUMP=objdump
-	STRIP=strip
-	WINDRES=windres
-endif
-
-# because Apple screws with us on this
-# need to get bintools from homebrew
-ifdef MACOSX
-	CC=clang
-	CXX=clang
-	OBJCOPY=gobjcopy
-	OBJDUMP=gobjdump
-endif
-
-# Automatically set version flag, but not if one was manually set
-# And don't bother if this is a clean only run
-ifeq   (,$(filter GCC% CLEANONLY,$(.VARIABLES)))
- version:=$(shell $(CC) --version)
- # check if this is in fact GCC
- ifneq (,$(or $(findstring gcc,$(version)),$(findstring GCC,$(version))))
-  version:=$(shell $(CC) -dumpversion)
-
-  # Turn version into words of major, minor
-  v:=$(subst ., ,$(version))
-  # concat. major minor
-  v:=$(word 1,$(v))$(word 2,$(v))
-
-  # If this version is not in the list, default to the latest supported
-  ifeq (,$(filter $(v),$(SUPPORTED_GCC_VERSIONS)))
-	define line =
-	Your compiler version, GCC $(version), is not supported by the Makefile.
-	The Makefile will assume GCC $(LATEST_GCC_VERSION).))
-	endef
-   $(call print,$(line))
-   GCC$(subst .,,$(LATEST_GCC_VERSION))=1
-  else
-   $(call print,Detected GCC $(version) (GCC$(v)))
-   GCC$(v)=1
-  endif
- endif
-endif
-
-ifdef GCC102
-GCC101=1
+# 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))))))
 
-ifdef GCC101
-GCC93=1
-endif
-
-ifdef GCC93
-GCC92=1
-endif
-
-ifdef GCC92
-GCC91=1
-endif
-
-ifdef GCC91
-GCC84=1
-endif
-
-ifdef GCC84
-GCC83=1
-endif
-
-ifdef GCC83
-GCC82=1
-endif
-
-ifdef GCC82
-GCC81=1
-endif
-
-ifdef GCC81
-GCC75=1
-endif
-
-ifdef GCC75
-GCC74=1
-endif
-
-ifdef GCC74
-GCC73=1
-endif
-
-ifdef GCC73
-GCC72=1
-endif
-
-ifdef GCC72
-GCC71=1
-endif
-
-ifdef GCC71
-GCC64=1
-endif
-
-ifdef GCC64
-GCC63=1
-endif
-
-ifdef GCC63
-GCC62=1
-endif
-
-ifdef GCC62
-GCC61=1
-endif
-
-ifdef GCC61
-GCC55=1
-endif
-
-ifdef GCC55
-GCC54=1
-endif
-
-ifdef GCC54
-GCC53=1
-endif
-
-ifdef GCC53
-GCC52=1
-endif
-
-ifdef GCC52
-GCC51=1
-endif
-
-ifdef GCC51
-GCC49=1
-endif
-
-ifdef GCC49
-GCC48=1
-endif
-
-ifdef GCC48
-GCC47=1
-endif
-
-ifdef GCC47
-GCC46=1
-endif
-
-ifdef GCC46
-GCC45=1
-endif
-
-ifdef GCC45
-GCC44=1
-endif
-
-ifdef GCC44
-GCC43=1
-endif
-
-ifdef GCC43
-GCC42=1
-endif
-
-ifdef GCC42
-GCC41=1
-endif
-
-ifdef GCC41
-GCC40=1
-VCHELP=1
-endif
-
-ifdef GCC295
-GCC29=1
-endif
-
-OLDWFLAGS:=$(WFLAGS)
 # -W -Wno-unused
-WFLAGS=-Wall
+WFLAGS:=-Wall
 ifndef GCC295
 #WFLAGS+=-Wno-packed
 endif
@@ -222,15 +30,13 @@ endif
 #WFLAGS+=-Wsystem-headers
 WFLAGS+=-Wfloat-equal
 #WFLAGS+=-Wtraditional
-ifdef VCHELP
- WFLAGS+=-Wdeclaration-after-statement
- WFLAGS+=-Wno-error=declaration-after-statement
-endif
  WFLAGS+=-Wundef
 ifndef GCC295
  WFLAGS+=-Wendif-labels
 endif
 ifdef GCC41
+ WFLAGS+=-Wdeclaration-after-statement
+ WFLAGS+=-Wno-error=declaration-after-statement
  WFLAGS+=-Wshadow
 endif
 #WFLAGS+=-Wlarger-than-%len%
@@ -308,8 +114,6 @@ ifdef ERRORMODE
 WFLAGS+=-Werror
 endif
 
-WFLAGS+=$(OLDWFLAGS)
-
 ifdef GCC43
  #WFLAGS+=-Wno-error=clobbered
 endif
@@ -338,141 +142,36 @@ ifdef GCC81
  WFLAGS+=-Wno-error=multistatement-macros
 endif
 
-
-#indicate platform and what interface use with
-ifndef LINUX
-ifndef FREEBSD
-ifndef CYGWIN32
-ifndef MINGW
-ifndef MINGW64
-ifndef SDL
-ifndef DUMMY
-$(error No interface or platform flag defined)
-endif
-endif
-endif
-endif
-endif
-endif
-endif
-
-#determine the interface directory (where you put all i_*.c)
-i_net_o=$(OBJDIR)/i_net.o
-i_system_o=$(OBJDIR)/i_system.o
-i_sound_o=$(OBJDIR)/i_sound.o
-i_main_o=$(OBJDIR)/i_main.o
-#set OBJDIR and BIN's starting place
-OBJDIR=../objs
-BIN=../bin
-DEPDIR=../dep
-#Nasm ASM and rm
-ifdef YASM
-NASM?=yasm
-else
-NASM?=nasm
-endif
-REMOVE?=rm -f
-MKDIR?=mkdir -p
-GZIP?=gzip
-GZIP_OPTS?=-9 -f -n
-GZIP_OPT2=$(GZIP_OPTS) --rsyncable
-UPX?=upx
-UPX_OPTS?=--best --preserve-build-id
-ifndef ECHO
-UPX_OPTS+=-q
-endif
-
-#Interface Setup
-ifdef DUMMY
-	INTERFACE=dummy
-	OBJDIR:=$(OBJDIR)/dummy
-	BIN:=$(BIN)/dummy
-	DEPDIR:=$(DEPDIR)/dummy
-else
-ifdef LINUX
-	NASMFORMAT=elf -DLINUX
-	SDL=1
-ifdef LINUX64
-	OBJDIR:=$(OBJDIR)/Linux64
-	BIN:=$(BIN)/Linux64
-	DEPDIR:=$(DEPDIR)/Linux64
+ifdef NONX86
+  ifdef X86_64 # yeah that SEEMS contradictory
+  opts+=-march=nocona
+  endif
 else
-	OBJDIR:=$(OBJDIR)/Linux
-	BIN:=$(BIN)/Linux
-	DEPDIR:=$(DEPDIR)/Linux
+  ifndef GCC29
+  opts+=-msse3 -mfpmath=sse
+  else
+  opts+=-mpentium
+  endif
 endif
-else
-ifdef FREEBSD
-	INTERFACE=sdl
-	NASMFORMAT=elf -DLINUX
-	SDL=1
-
-	OBJDIR:=$(OBJDIR)/FreeBSD
-	BIN:=$(BIN)/FreeBSD
-	DEPDIR:=$(DEPDIR)/Linux
-else
-ifdef SOLARIS
-	INTERFACE=sdl
-	NASMFORMAT=elf -DLINUX
-	SDL=1
 
-	OBJDIR:=$(OBJDIR)/Solaris
-	BIN:=$(BIN)/Solaris
-	DEPDIR:=$(DEPDIR)/Solaris
-else
-ifdef CYGWIN32
-	INTERFACE=sdl
-	NASMFORMAT=win32
-	SDL=1
-
-	OBJDIR:=$(OBJDIR)/cygwin
-	BIN:=$(BIN)/Cygwin
-	DEPDIR:=$(DEPDIR)/Cygwin
-else
-ifdef MINGW64
-	#NASMFORMAT=win64
-	SDL=1
-	OBJDIR:=$(OBJDIR)/Mingw64
-	BIN:=$(BIN)/Mingw64
-	DEPDIR:=$(DEPDIR)/Mingw64
+ifdef DEBUGMODE
+ifdef GCC48
+opts+=-Og
 else
-ifdef MINGW
-	NASMFORMAT=win32
-	SDL=1
-	OBJDIR:=$(OBJDIR)/Mingw
-	BIN:=$(BIN)/Mingw
-	DEPDIR:=$(DEPDIR)/Mingw
-endif
-endif
-endif
-endif
-endif
+opts+=O0
 endif
 endif
 
-ifdef ARCHNAME
-	OBJDIR:=$(OBJDIR)/$(ARCHNAME)
-	BIN:=$(BIN)/$(ARCHNAME)
-	DEPDIR:=$(DEPDIR)/$(ARCHNAME)
+ifdef VALGRIND
+ifdef GCC46
+WFLAGS+=-Wno-error=unused-but-set-variable
+WFLAGS+=-Wno-unused-but-set-variable
 endif
-
-OBJDUMP_OPTS?=--wide --source --line-numbers
-LD=$(CC)
-
-ifdef SDL
-	INTERFACE=sdl
-	OBJDIR:=$(OBJDIR)/SDL
-	DEPDIR:=$(DEPDIR)/SDL
 endif
 
-ifndef DUMMY
-ifdef DEBUGMODE
-	OBJDIR:=$(OBJDIR)/Debug
-	BIN:=$(BIN)/Debug
-	DEPDIR:=$(DEPDIR)/Debug
-else
-	OBJDIR:=$(OBJDIR)/Release
-	BIN:=$(BIN)/Release
-	DEPDIR:=$(DEPDIR)/Release
+# 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
index 702ae3765ce52effaccb48b7d3c3e196a7ac9214..0c671b26876e1740c1ab101a711b561f9ad2dd7a 100644
--- a/src/Makefile.d/win32.mk
+++ b/src/Makefile.d/win32.mk
@@ -1,136 +1,99 @@
 #
-# win32/Makefile.cfg for SRB2/Minwgw
+# Mingw, if you don't know, that's Win32/Win64
 #
 
-#
-#Mingw, if you don't know, that's Win32/Win64
-#
-
-ifdef MINGW64
-	HAVE_LIBGME=1
-	LIBGME_CFLAGS=-I../libs/gme/include
-	LIBGME_LDFLAGS=-L../libs/gme/win64 -lgme
-ifdef HAVE_OPENMPT
-	LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc
-	LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86_64/mingw -lopenmpt
-endif
-ifndef NOMIXERX
-	HAVE_MIXERX=1
-	SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main
-	SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDLMixerX/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
-else
-	SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main
-	SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDL2_mixer/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
-endif
-else
-	HAVE_LIBGME=1
-	LIBGME_CFLAGS=-I../libs/gme/include
-	LIBGME_LDFLAGS=-L../libs/gme/win32 -lgme
-ifdef HAVE_OPENMPT
-	LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc
-	LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86/mingw -lopenmpt
-endif
-ifndef NOMIXERX
-	HAVE_MIXERX=1
-	SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main
-	SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDLMixerX/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
+ifndef MINGW64
+EXENAME?=srb2win.exe
 else
-	SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main
-	SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDL2_mixer/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
-endif
+EXENAME?=srb2win64.exe
 endif
 
-ifndef NOASM
-	USEASM=1
-endif
+sources+=win32/Srb2win.rc
+opts+=-DSTDC_HEADERS
+libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32
 
-ifndef NONET
-ifndef MINGW64 #miniupnc is broken with MINGW64
-	HAVE_MINIUPNPC=1
-endif
-endif
+nasm_format:=win32
 
-	OPTS=-DSTDC_HEADERS
+SDL=1
 
-ifndef GCC44
-	#OPTS+=-mms-bitfields
+ifndef NOHW
+opts+=-DUSE_WGL_SWAP
 endif
 
-	LIBS+=-ladvapi32 -lkernel32 -lmsvcrt -luser32
 ifdef MINGW64
-	LIBS+=-lws2_32
+libs+=-lws2_32
 else
 ifdef NO_IPV6
-	LIBS+=-lwsock32
+libs+=-lwsock32
 else
-	LIBS+=-lws2_32
+libs+=-lws2_32
 endif
 endif
 
-	# name of the exefile
-	EXENAME?=srb2win.exe
-
-ifdef SDL
-	i_system_o+=$(OBJDIR)/SRB2.res
-	#i_main_o+=$(OBJDIR)/win_dbg.o
-ifndef NOHW
-	OPTS+=-DUSE_WGL_SWAP
+ifndef NONET
+ifndef MINGW64 # miniupnc is broken with MINGW64
+opts+=-I../libs -DSTATIC_MINIUPNPC
+libs+=-L../libs/miniupnpc/mingw$(32) -lws2_32 -liphlpapi
 endif
 endif
 
-
-ZLIB_CFLAGS?=-I../libs/zlib
-ifdef MINGW64
-ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz64
+ifndef MINGW64
+32=32
+x86=x86
+i686=i686
 else
-ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz32
+32=64
+x86=x86_64
+i686=x86_64
 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
+mingw:=$(i686)-w64-mingw32
 
-ifdef HAVE_MINIUPNPC
-	CPPFLAGS+=-I../libs/ -DSTATIC_MINIUPNPC
-ifdef MINGW64
-	LDFLAGS+=-L../libs/miniupnpc/mingw64
+define _set =
+$(1)_CFLAGS?=$($(1)_opts)
+$(1)_LDFLAGS?=$($(1)_libs)
+endef
+
+lib:=../libs/gme
+LIBGME_opts:=-I$(lib)/include
+LIBGME_libs:=-L$(lib)/win$(32) -lgme
+$(eval $(call _set,LIBGME))
+
+lib:=../libs/libopenmpt
+LIBOPENMPT_opts:=-I$(lib)/inc
+LIBOPENMPT_libs:=-L$(lib)/lib/$(x86)/mingw -lopenmpt
+$(eval $(call _set,LIBOPENMPT))
+
+ifndef NOMIXERX
+HAVE_MIXERX=1
+lib:=../libs/SDLMixerX/$(mingw)
 else
-	LDFLAGS+=-L../libs/miniupnpc/mingw32
-endif #MINGW64
+lib:=../libs/SDL2_mixer/$(mingw)
 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
+mixer_opts:=-I$(lib)/include/SDL2
+mixer_libs:=-L$(lib)/lib
+
+lib:=../libs/SDL2/$(mingw)
+SDL_opts:=-I$(lib)/include/SDL2\
+	$(mixer_opts) -Dmain=SDL_main
+SDL_libs:=-L$(lib)/lib $(mixer_libs)\
+	-lmingw32 -lSDL2main -lSDL2 -mwindows
+$(eval $(call _set,SDL))
+
+lib:=../libs/zlib
+ZLIB_opts:=-I$(lib)
+ZLIB_libs:=-L$(lib)/win32 -lz$(32)
+$(eval $(call _set,ZLIB))
+
+ifndef PNG_CONFIG
+lib:=../libs/libpng-src
+PNG_opts:=-I$(lib)
+PNG_libs:=-L$(lib)/projects -lpng$(32)
+$(eval $(call _set,PNG))
 endif
+
+lib:=../libs/curl
+CURL_opts:=-I$(lib)/include
+CURL_libs:=-L$(lib)/lib$(32) -lcurl
+$(eval $(call _set,CURL))
diff --git a/src/Sourcefile b/src/Sourcefile
new file mode 100644
index 0000000000000000000000000000000000000000..9f27f2810fcd02c81d41ad740e798b912f6936cd
--- /dev/null
+++ b/src/Sourcefile
@@ -0,0 +1,87 @@
+string.c
+d_main.c
+d_clisrv.c
+d_net.c
+d_netfil.c
+d_netcmd.c
+dehacked.c
+z_zone.c
+f_finale.c
+f_wipe.c
+g_demo.c
+g_game.c
+g_input.c
+am_map.c
+command.c
+console.c
+hu_stuff.c
+y_inter.c
+st_stuff.c
+m_aatree.c
+m_anigif.c
+m_argv.c
+m_bbox.c
+m_cheat.c
+m_cond.c
+m_fixed.c
+m_menu.c
+m_misc.c
+m_random.c
+m_queue.c
+info.c
+p_ceilng.c
+p_enemy.c
+p_floor.c
+p_inter.c
+p_lights.c
+p_map.c
+p_maputl.c
+p_mobj.c
+p_polyobj.c
+p_saveg.c
+p_setup.c
+p_sight.c
+p_spec.c
+p_telept.c
+p_tick.c
+p_user.c
+p_slopes.c
+tables.c
+r_bsp.c
+r_data.c
+r_draw.c
+r_main.c
+r_plane.c
+r_segs.c
+r_skins.c
+r_sky.c
+r_splats.c
+r_things.c
+r_textures.c
+r_picformats.c
+r_portal.c
+screen.c
+v_video.c
+s_sound.c
+sounds.c
+w_wad.c
+filesrch.c
+mserv.c
+http-mserv.c
+i_tcp.c
+lzf.c
+vid_copy.s
+b_bot.c
+lua_script.c
+lua_baselib.c
+lua_mathlib.c
+lua_hooklib.c
+lua_consolelib.c
+lua_infolib.c
+lua_mobjlib.c
+lua_playerlib.c
+lua_skinlib.c
+lua_thinkerlib.c
+lua_maplib.c
+lua_blockmaplib.c
+lua_hudlib.c
diff --git a/src/blua/Sourcefile b/src/blua/Sourcefile
new file mode 100644
index 0000000000000000000000000000000000000000..f99c89c8dfb8e8b5da643cb2c8625a764e84580d
--- /dev/null
+++ b/src/blua/Sourcefile
@@ -0,0 +1,25 @@
+lapi.c
+lbaselib.c
+ldo.c
+lfunc.c
+linit.c
+liolib.c
+llex.c
+lmem.c
+lobject.c
+lstate.c
+lstrlib.c
+ltablib.c
+lundump.c
+lzio.c
+lauxlib.c
+lcode.c
+ldebug.c
+ldump.c
+lgc.c
+lopcodes.c
+lparser.c
+lstring.c
+ltable.c
+ltm.c
+lvm.c
diff --git a/src/hardware/Sourcefile b/src/hardware/Sourcefile
new file mode 100644
index 0000000000000000000000000000000000000000..1c05de76cca6d71251023e3e9e7bdde7d8cffaab
--- /dev/null
+++ b/src/hardware/Sourcefile
@@ -0,0 +1,13 @@
+hw_bsp.c
+hw_draw.c
+hw_light.c
+hw_main.c
+hw_clip.c
+hw_md2.c
+hw_cache.c
+hw_md2load.c
+hw_md3load.c
+hw_model.c
+u_list.c
+hw_batching.c
+r_opengl/r_opengl.c
diff --git a/src/sdl/Sourcefile b/src/sdl/Sourcefile
new file mode 100644
index 0000000000000000000000000000000000000000..82d5ce0734eb30684cee1ee875f8e94e481bd5ad
--- /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