diff --git a/CMakeLists.txt b/CMakeLists.txt
index abec11087..85f469a9f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
 # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
 # Version change is fine.
 project(SRB2
-	VERSION 2.2.2
+	VERSION 2.2.3
 	LANGUAGES C)
 
 if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
diff --git a/appveyor.yml b/appveyor.yml
index a28935f63..8d370301d 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 2.2.2.{branch}-{build}
+version: 2.2.3.{branch}-{build}
 os: MinGW
 
 environment:
diff --git a/src/config.h.in b/src/config.h.in
index 4926f9a06..18320f96b 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -28,12 +28,13 @@
 /* Manually defined asset hashes for non-CMake builds
  * Last updated 2020 / 02 / 15 - v2.2.1 - main assets
  * Last updated 2020 / 02 / 22 - v2.2.2 - patch.pk3
+ * Last updated 2020 / 05 / 10 - v2.2.3 - player.dta & patch.pk3
  */
 #define ASSET_HASH_SRB2_PK3   "0277c9416756627004e83cbb5b2e3e28"
 #define ASSET_HASH_ZONES_PK3  "f7e88afb6af7996a834c7d663144bead"
-#define ASSET_HASH_PLAYER_DTA "ad49e07b17cc662f1ad70c454910b4ae"
+#define ASSET_HASH_PLAYER_DTA "8a4507ddf9bc0682c09174400f26ad65"
 #ifdef USE_PATCH_DTA
-#define ASSET_HASH_PATCH_PK3  "ee54330ecb743314c5f962af4db731ff"
+#define ASSET_HASH_PATCH_PK3  "d56064ff33a0a4a17d38512cbcb5613d"
 #endif
 
 #endif
diff --git a/src/doomdef.h b/src/doomdef.h
index a91142e9d..16f3d4783 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -143,9 +143,9 @@ extern char logfilename[1024];
 // we use comprevision and compbranch instead.
 #else
 #define VERSION    202 // Game version
-#define SUBVERSION 2  // more precise version number
-#define VERSIONSTRING "v2.2.2"
-#define VERSIONSTRINGW L"v2.2.2"
+#define SUBVERSION 3  // more precise version number
+#define VERSIONSTRING "v2.2.3"
+#define VERSIONSTRINGW L"v2.2.3"
 // Hey! If you change this, add 1 to the MODVERSION below!
 // Otherwise we can't force updates!
 #endif
@@ -213,7 +213,7 @@ extern char logfilename[1024];
 // it's only for detection of the version the player is using so the MS can alert them of an update.
 // Only set it higher, not lower, obviously.
 // Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1".
-#define MODVERSION 42
+#define MODVERSION 43
 
 // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
 // Increment MINOREXECVERSION whenever a config change is needed that does not correspond
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 565076b95..69da6655a 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -4019,7 +4019,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
 }
 
 // This is expecting a pointer to an array containing 4 wallVerts for a sprite
-static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts)
+static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts, const boolean precip)
 {
 	if (cv_grspritebillboarding.value
 		&& spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)
@@ -4027,7 +4027,7 @@ static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts
 	{
 		float basey = FIXED_TO_FLOAT(spr->mobj->z);
 		float lowy = wallVerts[0].y;
-		if (P_MobjFlip(spr->mobj) == -1)
+		if (!precip && P_MobjFlip(spr->mobj) == -1) // precip doesn't have eflags so they can't flip
 		{
 			basey = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
 		}
@@ -4140,7 +4140,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 	}
 
 	// Let dispoffset work first since this adjust each vertex
-	HWR_RotateSpritePolyToAim(spr, baseWallVerts);
+	HWR_RotateSpritePolyToAim(spr, baseWallVerts, false);
 
 	realtop = top = baseWallVerts[3].y;
 	realbot = bot = baseWallVerts[0].y;
@@ -4419,7 +4419,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 	}
 
 	// Let dispoffset work first since this adjust each vertex
-	HWR_RotateSpritePolyToAim(spr, wallVerts);
+	HWR_RotateSpritePolyToAim(spr, wallVerts, false);
 
 	// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
 	// sprite lighting by modulating the RGB components
@@ -4503,7 +4503,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
 	wallVerts[1].z = wallVerts[2].z = spr->z2;
 
 	// Let dispoffset work first since this adjust each vertex
-	HWR_RotateSpritePolyToAim(spr, wallVerts);
+	HWR_RotateSpritePolyToAim(spr, wallVerts, true);
 
 	wallVerts[0].sow = wallVerts[3].sow = 0;
 	wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s;
diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c
index 5d0009927..3eded734f 100644
--- a/src/sdl/i_main.c
+++ b/src/sdl/i_main.c
@@ -27,7 +27,7 @@
 #include <unistd.h>
 #endif
 
-#ifdef __unix__
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
 #include <errno.h>
 #endif
 
@@ -142,7 +142,7 @@ int main(int argc, char **argv)
 		const char *reldir;
 		int left;
 		boolean fileabs;
-#ifdef __unix__
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
 		const char *link;
 #endif
 
@@ -201,7 +201,7 @@ int main(int argc, char **argv)
 				M_PathParts(logdir) - 1,
 				M_PathParts(logfilename) - 1, 0755);
 
-#ifdef __unix__
+#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
 		logstream = fopen(logfilename, "w");
 #ifdef DEFAULTDIR
 		if (logdir)
@@ -214,9 +214,9 @@ int main(int argc, char **argv)
 		{
 			I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno));
 		}
-#else/*__unix__*/
+#else/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
 		logstream = fopen("latest-log.txt", "wt+");
-#endif/*__unix__*/
+#endif/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/
 	}
 
 	//I_OutputMsg("I_StartupSystem() ...\n");
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index a86af316e..d2ed62516 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -2484,7 +2484,7 @@ void I_RemoveExitFunc(void (*func)())
 	}
 }
 
-#ifndef __unix__
+#if !(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON))
 static void Shittycopyerror(const char *name)
 {
 	I_OutputMsg(
@@ -2524,7 +2524,7 @@ static void Shittylogcopy(void)
 		Shittycopyerror(logfilename);
 	}
 }
-#endif/*__unix__*/
+#endif/*!(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON))*/
 
 //
 //  Closes down everything. This includes restoring the initial
@@ -2548,7 +2548,7 @@ void I_ShutdownSystem(void)
 	if (logstream)
 	{
 		I_OutputMsg("I_ShutdownSystem(): end of logstream.\n");
-#ifndef __unix__
+#if !(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON))
 		Shittylogcopy();
 #endif
 		fclose(logstream);
diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
index 182220265..1ed28bd14 100644
--- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
+++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
@@ -1219,7 +1219,7 @@
 		C01FCF4B08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.2.2;
+				CURRENT_PROJECT_VERSION = 2.2.3;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"$(inherited)",
 					NORMALSRB2,
@@ -1231,7 +1231,7 @@
 		C01FCF4C08A954540054247B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.2.2;
+				CURRENT_PROJECT_VERSION = 2.2.3;
 				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_PREPROCESSOR_DEFINITIONS = (