diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b5c43d0173b257c65622f434c7c82d4d80304526
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,63 @@
+version: 2
+jobs:
+  build:
+    working_directory: /root/SRB2
+    docker:
+      - image: debian:jessie
+        environment:
+          CC: ccache gcc -m32
+          PKG_CONFIG_LIBDIR: /usr/lib/i386-linux-gnu/pkgconfig
+          LIBGME_CFLAGS: -I/usr/include
+          LIBGME_LDFLAGS: -lgme
+          CCACHE_COMPRESS: true
+          WFLAGS: -Wno-unsuffixed-float-constants
+          GCC49: true
+      #- image: ubuntu:trusty
+      #  environment:
+      #    CC: ccache gcc -m32
+      #    PKG_CONFIG_LIBDIR: /usr/lib/i386-linux-gnu/pkgconfig
+      #    LIBGME_CFLAGS: -I/usr/include
+      #    LIBGME_LDFLAGS: -lgme
+      #    CCACHE_COMPRESS: true
+      #    WFLAGS: -Wno-unsuffixed-float-constants
+      #    GCC48: true
+    steps:
+      - run:
+          name: Add i386 arch
+          command: dpkg --add-architecture i386
+      - run:
+          name: Update APT listing
+          command: apt-get -qq update
+      - run:
+          name: Support S3 upload
+          command: apt-get -qq -y install ca-certificates
+      - restore_cache:
+          keys:
+            - v1-SRB2-APT
+      - run:
+          name: Install SDK
+          command: apt-get -qq -y install git build-essential nasm libpng12-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx
+      - save_cache:
+          key: v1-SRB2-APT
+          paths:
+            - /var/cache/apt/archives
+      - checkout
+      - run:
+          name: Clean build
+          command: make -C src LINUX=1 clean
+      - restore_cache:
+          keys:
+            - v1-SRB2-{{ .Branch }}-{{ checksum "objs/Linux/SDL/Release/depend.dep" }}
+      - run:
+          name: Compile
+          command: make -C src LINUX=1 ERRORMODE=1 -k
+      - store_artifacts:
+          path: /root/SRB2/bin/Linux/Release/
+          destination: bin
+      - save_cache:
+          key: v1-SRB2-{{ .Branch }}-{{ checksum "objs/Linux/SDL/Release/depend.dep" }}
+          paths:
+            - /root/.ccache
+
+
+
diff --git a/README.md b/README.md
index eb06156b4673c7656512ed16528b0edbbada3970..d16071454876bc178222e778ca7c20f63821bb97 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
 
 [![Build status](https://ci.appveyor.com/api/projects/status/399d4hcw9yy7hg2y?svg=true)](https://ci.appveyor.com/project/STJr/srb2)
 [![Build status](https://travis-ci.org/STJr/SRB2.svg?branch=master)](https://travis-ci.org/STJr/SRB2)
+[![CircleCI](https://circleci.com/gh/STJr/SRB2/tree/master.svg?style=svg)](https://circleci.com/gh/STJr/SRB2/tree/master)
 
 [Sonic Robo Blast 2](https://srb2.org/) is a 3D Sonic the Hedgehog fangame based on a modified version of [Doom Legacy](http://doomlegacy.sourceforge.net/).
 
diff --git a/appveyor.yml b/appveyor.yml
index 25b95d292791f5dc11e67431133b3fbc8fcb6c0d..b0544a90b549ab0e526e2f0902a8b4093837478f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -47,7 +47,7 @@ before_build:
 - upx -V
 - ccache -V
 - ccache -s
-- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC53=1 CCACHE=1
+- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1
 
 build_script:
 - cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean
diff --git a/src/Makefile.cfg b/src/Makefile.cfg
index 72404becca345b380fb9a60795f3a05734337db3..80d018c4b5993ad01e1ddbfd34cff1f2564a3398 100644
--- a/src/Makefile.cfg
+++ b/src/Makefile.cfg
@@ -7,6 +7,23 @@
 # and other things
 #
 
+
+ifdef GCC63
+GCC62=1
+endif
+
+ifdef GCC62
+GCC61=1
+endif
+
+ifdef GCC61
+GCC54=1
+endif
+
+ifdef GCC54
+GCC53=1
+endif
+
 ifdef GCC53
 GCC52=1
 endif
@@ -164,19 +181,29 @@ ifdef GCC45
 WFLAGS+=-Wunsuffixed-float-constants
 endif
 endif
+
 ifdef NOLDWARNING
 LDFLAGS+=-Wl,--as-needed
 endif
+
 ifdef ERRORMODE
 WFLAGS+=-Werror
 endif
+
+WFLAGS+=$(OLDWFLAGS)
+
 ifdef GCC43
  #WFLAGS+=-Wno-error=clobbered
 endif
 ifdef GCC46
  WFLAGS+=-Wno-error=suggest-attribute=noreturn
 endif
-WFLAGS+=$(OLDWFLAGS)
+ifdef GCC54
+ WFLAGS+=-Wno-logical-op -Wno-error=logical-op
+endif
+ifdef GCC61
+ WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare
+endif
 
 
 #indicate platform and what interface use with
diff --git a/src/d_main.c b/src/d_main.c
index 2caf50087407c4f60ac8f6e1d0ee2ef2c2176e27..4080087c1245d71ecc07e65a9613df365e316883 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -187,7 +187,7 @@ UINT8 altdown = 0; // 0x1 left, 0x2 right
 //
 static inline void D_ModifierKeyResponder(event_t *ev)
 {
-	if (ev->type == ev_keydown) switch (ev->data1)
+	if (ev->type == ev_keydown || ev->type == ev_console) switch (ev->data1)
 	{
 		case KEY_LSHIFT: shiftdown |= 0x1; return;
 		case KEY_RSHIFT: shiftdown |= 0x2; return;
diff --git a/src/d_net.c b/src/d_net.c
index fae1ea311dcf87f1f19c4eb9b6781de4e7e26bf4..7f16c302d1c3267c0f1b5476b3e4b10cbfb6593f 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -991,12 +991,14 @@ void Command_Droprate(void)
 	packetdroprate = droprate;
 }
 
+#ifndef NONET
 static boolean ShouldDropPacket(void)
 {
 	return (packetdropquantity[netbuffer->packettype])
 		|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
 }
 #endif
+#endif
 
 //
 // HSendPacket
diff --git a/src/g_game.c b/src/g_game.c
index 84db90132b0b1dafebaf77b8f48411eaec2b0534..7499fe7a0e362209d4f27cb96c98243262c008e5 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -2888,7 +2888,7 @@ static void G_DoCompleted(void)
 	if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
 		P_AllocMapHeader(nextmap);
 
-	if (skipstats)
+	if (skipstats && !modeattacking) // Don't skip stats if we're in record attack
 		G_AfterIntermission();
 	else
 	{
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 54dd9485439db543f69f846480ef3719ea32ad88..3a0bf70544b4b63e25f64b00595e5d2976eb758b 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -1836,7 +1836,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
 	}
 }
 
-static inline void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color)
+static  void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color)
 {
 	INT32     val, count, pindex;
 	GLfloat s, t;
diff --git a/src/r_bsp.c b/src/r_bsp.c
index 2562cff666217e75e5c43be0acf065c6dbc20980..44cb991a7000fbea276aa64b1e8f07d5d1314254 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -210,7 +210,7 @@ void R_PortalClearClipSegs(INT32 start, INT32 end)
 //
 // It assumes that Doom has already ruled out a door being closed because
 // of front-back closure (e.g. front floor is taller than back ceiling).
-static inline INT32 R_DoorClosed(void)
+static INT32 R_DoorClosed(void)
 {
 	return
 
diff --git a/src/r_segs.c b/src/r_segs.c
index 8f271bfe3df8b9ca6e39e9d6d89372888bc1d752..502ff3304dab17ec4f54283608ee33fb74145b60 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -706,10 +706,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 // Loop through R_DrawMaskedColumn calls
 static void R_DrawRepeatMaskedColumn(column_t *col)
 {
-	do {
+	while (sprtopscreen < sprbotscreen) {
 		R_DrawMaskedColumn(col);
-		sprtopscreen += dc_texheight*spryscale;
-	} while (sprtopscreen < sprbotscreen);
+		if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
+			sprtopscreen = INT32_MAX;
+		else
+			sprtopscreen += dc_texheight*spryscale;
+	}
 }
 
 //
diff --git a/src/r_things.c b/src/r_things.c
index 927217c5c3df0c10ad3dcf9f5b8340ddfc83d61b..331febabd41c4a5bda0e77c574f31548fcc9c19d 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -891,12 +891,18 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
 #endif
 	fixed_t frac;
 	patch_t *patch;
+	INT64 overflow_test;
 
 	//Fab : R_InitSprites now sets a wad lump number
 	patch = W_CacheLumpNum(vis->patch, PU_CACHE);
 	if (!patch)
 		return;
 
+	// Check for overflow
+	overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS);
+	if (overflow_test < 0) overflow_test = -overflow_test;
+	if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow
+
 	if (vis->transmap)
 	{
 		colfunc = fuzzcolfunc;