shithub: cstory

Download patch

ref: 1d9048c8a6a6388607799384d4912eec00e88c5d
parent: afd3abecc44812a0748caac0fa47b0612f62160d
parent: 7c729af36f42271a9f0e0184cd36a7192f599917
author: Gabriel Ravier <[email protected]>
date: Sat Apr 4 21:16:09 EDT 2020

Merge branch 'portable' into improvePerformance2

# Conflicts:
#	src/Backends/Rendering/Software.cpp

--- a/.travis.yml
+++ b/.travis.yml
@@ -56,6 +56,18 @@
     - PLATFORM=GLFW3 AUDIO=miniaudio RENDERER=OpenGL3
     - PLATFORM=GLFW3 AUDIO=miniaudio RENDERER=OpenGLES2
 
+jobs:
+  exclude:
+    # macOS doesn't support OpenGLES2, apparently
+    - os: osx
+      env: PLATFORM=SDL2 AUDIO=SDL2 RENDERER=OpenGLES2
+    - os: osx
+      env: PLATFORM=GLFW3 AUDIO=miniaudio RENDERER=OpenGLES2
+    # GCC is mysteriously broken when trying to parse macOS headers for miniaudio
+    - os: osx
+      compiler: gcc
+      env: PLATFORM=GLFW3 AUDIO=miniaudio RENDERER=OpenGL3
+
 before_install:
     # Set URL for Discord send script
     - DISCORD_SEND_SCRIPT_URL=https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -168,7 +168,7 @@
 	"src/WindowsWrapper.h"
 	"src/Backends/Audio.h"
 	"src/Backends/Controller.h"
-	"src/Backends/Platform.h"
+	"src/Backends/Misc.h"
 	"src/Backends/Rendering.h"
 )
 
@@ -303,9 +303,17 @@
 endif()
 
 if(BACKEND_AUDIO MATCHES "SDL2")
-	target_sources(CSE2 PRIVATE "src/Backends/Audio/SDL2.cpp" "src/Backends/Audio/SoftwareMixer.cpp" "src/Backends/Audio/SoftwareMixer.h")
+	target_sources(CSE2 PRIVATE
+		"src/Backends/Audio/SDL2.cpp"
+		"src/Backends/Audio/SoftwareMixer.cpp"
+		"src/Backends/Audio/SoftwareMixer.h"
+	)
 elseif(BACKEND_AUDIO MATCHES "miniaudio")
-	target_sources(CSE2 PRIVATE "src/Backends/Audio/miniaudio.cpp" "src/Backends/Audio/SoftwareMixer.cpp" "src/Backends/Audio/SoftwareMixer.h")
+	target_sources(CSE2 PRIVATE
+		"src/Backends/Audio/miniaudio.cpp"
+		"src/Backends/Audio/SoftwareMixer.cpp"
+		"src/Backends/Audio/SoftwareMixer.h"
+	)
 
 	# Link libdl, libm, and libpthread
 	include(CheckLibraryExists)
@@ -326,22 +334,31 @@
 endif()
 
 if(BACKEND_PLATFORM MATCHES "SDL2")
-	target_sources(CSE2 PRIVATE "src/Backends/Platform/SDL2.cpp" "src/Backends/Controller/SDL2.cpp")
+	target_sources(CSE2 PRIVATE
+		"src/Backends/SDL2/Controller.cpp"
+		"src/Backends/SDL2/Controller.h"
+		"src/Backends/SDL2/Misc.cpp"
+		"src/Backends/SDL2/Window.h"
+	)
 elseif(BACKEND_PLATFORM MATCHES "GLFW3")
-	target_sources(CSE2 PRIVATE "src/Backends/Platform/GLFW3.cpp" "src/Backends/Controller/GLFW3.cpp")
+	target_sources(CSE2 PRIVATE
+		"src/Backends/GLFW3/Controller.cpp"
+		"src/Backends/GLFW3/Misc.cpp"
+		"src/Backends/GLFW3/Window.h"
+	)
 endif()
 
 if(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "OpenGL3")
-	target_sources(CSE2 PRIVATE "src/Backends/Window/SDL2-OpenGL3.cpp")
+	target_sources(CSE2 PRIVATE "src/Backends/SDL2/Window-OpenGL3.cpp")
 elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "OpenGLES2")
-	target_sources(CSE2 PRIVATE "src/Backends/Window/SDL2-OpenGLES2.cpp")
+	target_sources(CSE2 PRIVATE "src/Backends/SDL2/Window-OpenGLES2.cpp")
 elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "SDLTexture")
 elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "SDLSurface")
 elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "Software")
 elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "OpenGL3")
-	target_sources(CSE2 PRIVATE "src/Backends/Window/GLFW3-OpenGL3.cpp")
+	target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-OpenGL3.cpp")
 elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "OpenGLES2")
-	target_sources(CSE2 PRIVATE "src/Backends/Window/GLFW3-OpenGLES2.cpp")
+	target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-OpenGLES2.cpp")
 else()
 	message(FATAL_ERROR "Invalid BACKEND_PLATFORM/BACKEND_RENDERER combination")
 endif()
@@ -526,10 +543,11 @@
 endif()
 
 if(BACKEND_RENDERER MATCHES "OpenGL3")
-	target_sources(CSE2 PRIVATE "external/glad/src/glad.c" "external/glad/include/glad/glad.h" "external/glad/include/KHR/khrplatform.h")
+	add_subdirectory("external/glad" EXCLUDE_FROM_ALL)
+	target_link_libraries(CSE2 PRIVATE glad)
 
 	find_package(OpenGL REQUIRED)
-	target_link_libraries(CSE2 PRIVATE OpenGL::GL ${CMAKE_DL_LIBS})
+	target_link_libraries(CSE2 PRIVATE OpenGL::GL)
 endif()
 
 if(BACKEND_RENDERER MATCHES "OpenGLES2")
--- a/DoConfig/CMakeLists.txt
+++ b/DoConfig/CMakeLists.txt
@@ -9,9 +9,6 @@
 
 add_executable(DoConfig WIN32
 	"icon.rc"
-	"../external/glad/include/glad/glad.h"
-	"../external/glad/include/KHR/khrplatform.h"
-	"../external/glad/src/glad.c"
 	"DoConfig.cpp"
 	"imgui/imconfig.h"
 	"imgui/imgui.cpp"
@@ -70,6 +67,16 @@
 ################
 # Dependencies #
 ################
+
+# glad
+
+add_subdirectory("../external/glad" "glad" EXCLUDE_FROM_ALL)
+target_link_libraries(DoConfig PRIVATE glad)
+
+find_package(OpenGL REQUIRED)
+target_link_libraries(DoConfig PRIVATE OpenGL::GL)
+
+# GLFW3
 
 if(NOT FORCE_LOCAL_LIBS)
 	find_package(PkgConfig QUIET)
--- a/cmake/FindOpenGLES2.cmake
+++ b/cmake/FindOpenGLES2.cmake
@@ -19,6 +19,57 @@
 # Win32, Apple, and Android are not tested!
 # Linux tested and works
 
+# Slightly customised framework finder
+macro(findpkg_framework fwk)
+  if(APPLE)
+    set(${fwk}_FRAMEWORK_PATH
+      ${${fwk}_FRAMEWORK_SEARCH_PATH}
+      ${CMAKE_FRAMEWORK_PATH}
+      ~/Library/Frameworks
+      /Library/Frameworks
+      /System/Library/Frameworks
+      /Network/Library/Frameworks
+      ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Release
+      ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Debug
+    )
+    # These could be arrays of paths, add each individually to the search paths
+    foreach(i ${OGRE_PREFIX_PATH})
+      set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug)
+    endforeach(i)
+
+    foreach(i ${OGRE_PREFIX_BUILD})
+      set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug)
+    endforeach(i)
+
+    foreach(dir ${${fwk}_FRAMEWORK_PATH})
+      set(fwkpath ${dir}/${fwk}.framework)
+      if(EXISTS ${fwkpath})
+        set(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES}
+          ${fwkpath}/Headers ${fwkpath}/PrivateHeaders)
+        set(${fwk}_FRAMEWORK_PATH ${dir})
+        if (NOT ${fwk}_LIBRARY_FWK)
+          set(${fwk}_LIBRARY_FWK "-framework ${fwk}")
+        endif ()
+      endif(EXISTS ${fwkpath})
+    endforeach(dir)
+  endif(APPLE)
+endmacro(findpkg_framework)
+
+macro(create_search_paths PREFIX)
+  foreach(dir ${${PREFIX}_PREFIX_PATH})
+    set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH}
+      ${dir}/include ${dir}/Include ${dir}/include/${PREFIX} ${dir}/Headers)
+    set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH}
+      ${dir}/lib ${dir}/Lib ${dir}/lib/${PREFIX} ${dir}/Libs)
+    set(${PREFIX}_BIN_SEARCH_PATH ${${PREFIX}_BIN_SEARCH_PATH}
+      ${dir}/bin)
+  endforeach(dir)
+  if(ANDROID)
+	set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} ${OGRE_DEPENDENCIES_DIR}/lib/${ANDROID_ABI})
+  endif()
+  set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH})
+endmacro(create_search_paths)
+
 if(WIN32)
 	if(CYGWIN)
 		find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h)
--- /dev/null
+++ b/external/glad/CMakeLists.txt
@@ -1,0 +1,16 @@
+cmake_minimum_required(VERSION 3.12)
+
+if(NOT TARGET glad)
+
+project(glad LANGUAGES C)
+
+add_library(glad
+	"include/glad/glad.h"
+	"include/KHR/khrplatform.h"
+	"src/glad.c"
+)
+
+target_include_directories(glad PUBLIC "include")
+target_link_libraries(glad PRIVATE ${CMAKE_DL_LIBS})
+
+endif(NOT TARGET glad)
--- a/external/glad/include/glad/glad.h
+++ b/external/glad/include/glad/glad.h
@@ -86,7 +86,7 @@
 
 GLAPI int gladLoadGLLoader(GLADloadproc);
 
-#include "../KHR/khrplatform.h"
+#include <KHR/khrplatform.h>
 typedef unsigned int GLenum;
 typedef unsigned char GLboolean;
 typedef unsigned int GLbitfield;
--- a/external/glad/src/glad.c
+++ b/external/glad/src/glad.c
@@ -22,7 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "../include/glad/glad.h"
+#include <glad/glad.h>
 
 static void* get_proc(const char *namez);
 
--- a/src/Backends/Audio/SDL2.cpp
+++ b/src/Backends/Audio/SDL2.cpp
@@ -5,7 +5,7 @@
 
 #include "SDL.h"
 
-#include "../Platform.h"
+#include "../Misc.h"
 #include "../../Organya.h"
 #include "../../WindowsWrapper.h"
 #include "../../Attributes.h"
@@ -67,7 +67,7 @@
 {
 	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
 	{
-		PlatformBackend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_InitSubSystem(SDL_INIT_AUDIO)' failed");
+		Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_InitSubSystem(SDL_INIT_AUDIO)' failed");
 		return FALSE;
 	}
 
@@ -77,10 +77,10 @@
 		puts(SDL_GetAudioDriver(i));
 
 	SDL_AudioSpec specification;
-	specification.freq = 44100;
+	specification.freq = 48000;
 	specification.format = AUDIO_F32;
 	specification.channels = 2;
-	specification.samples = 0x400;	// Roughly 10 milliseconds for 44100Hz
+	specification.samples = 0x400;	// Roughly 10 milliseconds for 48000Hz
 	specification.callback = Callback;
 	specification.userdata = NULL;
 
@@ -91,7 +91,7 @@
 
 	if (device_id == 0)
 	{
-		PlatformBackend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_OpenAudioDevice' failed");
+		Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_OpenAudioDevice' failed");
 		return FALSE;
 	}
 
--- a/src/Backends/Audio/miniaudio.cpp
+++ b/src/Backends/Audio/miniaudio.cpp
@@ -76,7 +76,7 @@
 	config.playback.pDeviceID = NULL;
 	config.playback.format = ma_format_f32;
 	config.playback.channels = 2;
-	config.sampleRate = 0;
+	config.sampleRate = 0;	// Let miniaudio decide what sample rate to use
 	config.dataCallback = Callback;
 	config.pUserData = NULL;
 
--- a/src/Backends/Controller.h
+++ b/src/Backends/Controller.h
@@ -4,7 +4,7 @@
 
 #include "../Input.h"
 
-void ControllerBackend_Deinit(void);
 BOOL ControllerBackend_Init(void);
+void ControllerBackend_Deinit(void);
 BOOL ControllerBackend_GetJoystickStatus(JOYSTICK_STATUS *status);
 BOOL ControllerBackend_ResetJoystickStatus(void);
--- a/src/Backends/Controller/GLFW3.cpp
+++ /dev/null
@@ -1,23 +1,0 @@
-#include "../Controller.h"
-
-#include "../../WindowsWrapper.h"
-
-void ControllerBackend_Deinit(void)
-{
-	
-}
-
-BOOL ControllerBackend_Init(void)
-{
-	return FALSE;
-}
-
-BOOL ControllerBackend_GetJoystickStatus(JOYSTICK_STATUS *status)
-{
-	return FALSE;
-}
-
-BOOL ControllerBackend_ResetJoystickStatus(void)
-{
-	return FALSE;
-}
--- a/src/Backends/Controller/SDL2.cpp
+++ /dev/null
@@ -1,116 +1,0 @@
-#include "../Controller.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "SDL.h"
-
-#include "../../WindowsWrapper.h"
-
-// The original names for these variables are unknown
-static SDL_Joystick *joystick = NULL;
-static int joystick_neutral_x = 0;
-static int joystick_neutral_y = 0;
-
-void ControllerBackend_Deinit(void)
-{
-	// Close opened joystick (if exists)
-	if (joystick != NULL)
-	{
-		SDL_JoystickClose(joystick);
-		joystick = NULL;
-	}
-
-	SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
-}
-
-// It looks like Pixel declared his functions early, so he could forward-reference
-BOOL FindAndOpenDirectInputDevice(void);
-
-BOOL ControllerBackend_Init(void)
-{
-	SDL_InitSubSystem(SDL_INIT_JOYSTICK);
-
-	if (!FindAndOpenDirectInputDevice())
-		return FALSE;
-
-	return TRUE;
-}
-
-// The original name for this function and its variables are unknown.
-// This function finds and hooks the first available DirectInput device (or SDL Joystick, in this case).
-BOOL FindAndOpenDirectInputDevice(void)
-{
-	int i;
-
-	for (i = 0; i < SDL_NumJoysticks(); ++i)
-		printf("Joystick #%d name: %s\n", i, SDL_JoystickNameForIndex(i));
-
-	// Open first available joystick
-	for (i = 0; i < SDL_NumJoysticks(); ++i)
-	{
-		joystick = SDL_JoystickOpen(i);
-
-		// Break as soon as a joystick is properly opened
-		if (joystick != NULL)
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-BOOL ControllerBackend_GetJoystickStatus(JOYSTICK_STATUS *status)
-{
-	if (joystick == NULL)
-		return FALSE;
-
-	// The original Input.cpp assumed there were 32 buttons (because of DirectInput's 'DIJOYSTATE' struct)
-	int numButtons = SDL_JoystickNumButtons(joystick);
-	if (numButtons > 32)
-		numButtons = 32;
-
-	// Read whatever buttons actually exist
-	int i = 0;
-	for (; i < numButtons; ++i)
-	{
-		if (SDL_JoystickGetButton(joystick, i) != 0)
-			status->bButton[i] = TRUE;
-		else
-			status->bButton[i] = FALSE;
-	}
-
-	// Blank the buttons that do not
-	for (; i < 32; ++i)
-		status->bButton[i] = FALSE;
-
-	status->bDown = FALSE;
-	status->bRight = FALSE;
-	status->bUp = FALSE;
-	status->bLeft = FALSE;
-
-	const Sint16 joystick_x = SDL_JoystickGetAxis(joystick, 0);
-	if (joystick_x < joystick_neutral_x - 10000)
-		status->bLeft = TRUE;
-	else if (joystick_x > joystick_neutral_x + 10000)
-		status->bRight = TRUE;
-
-	const Sint16 joystick_y = SDL_JoystickGetAxis(joystick, 1);
-	if (joystick_y < joystick_neutral_y - 10000)
-		status->bUp = TRUE;
-	else if (joystick_y > joystick_neutral_y + 10000)
-		status->bDown = TRUE;
-
-	return TRUE;
-}
-
-BOOL ControllerBackend_ResetJoystickStatus(void)
-{
-	if (joystick == NULL)
-		return FALSE;
-
-	joystick_neutral_x = SDL_JoystickGetAxis(joystick, 0);
-	joystick_neutral_y = SDL_JoystickGetAxis(joystick, 1);
-
-	return TRUE;
-}
--- /dev/null
+++ b/src/Backends/GLFW3/Controller.cpp
@@ -1,0 +1,124 @@
+#include "../Controller.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+
+#include "../../WindowsWrapper.h"
+
+#define DEADZONE (10000.0f / 32767.0f)
+
+static BOOL joystick_connected;
+static int connected_joystick_id;
+static int joystick_neutral_x;
+static int joystick_neutral_y;
+
+static void JoystickCallback(int joystick_id, int event)
+{
+	switch (event)
+	{
+		case GLFW_CONNECTED:
+			printf("Joystick #%d connected - %s\n", joystick_id, glfwGetJoystickName(joystick_id));
+
+			if (!joystick_connected)
+			{
+				int total_axis;
+				const float *axis = glfwGetJoystickAxes(joystick_id, &total_axis);
+
+				if (total_axis >= 2)
+				{
+#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3)
+					if (glfwJoystickIsGamepad(joystick_id) == GLFW_TRUE)	// Avoid selecting things like laptop touchpads
+#endif
+					{
+						printf("Joystick #%d selected\n", joystick_id);
+						joystick_connected = TRUE;
+						connected_joystick_id = joystick_id;
+
+						// Reset default stick positions (this is performed in ResetJoystickStatus in vanilla Cave Story
+						joystick_neutral_x = axis[0];
+						joystick_neutral_y = axis[1];
+					}
+				}
+			}
+
+			break;
+
+		case GLFW_DISCONNECTED:
+			if (joystick_connected && joystick_id == connected_joystick_id)
+			{
+				printf("Joystick #%d disconnected\n", connected_joystick_id);
+				joystick_connected = FALSE;
+			}
+
+			break;
+	}
+}
+
+BOOL ControllerBackend_Init(void)
+{
+	// Connect joysticks that are already plugged-in
+	for (int i = GLFW_JOYSTICK_1; i < GLFW_JOYSTICK_LAST; ++i)
+		if (glfwJoystickPresent(i) == GLFW_TRUE)
+			JoystickCallback(i, GLFW_CONNECTED);
+
+	// Set-up the callback for future (dis)connections
+	glfwSetJoystickCallback(JoystickCallback);
+
+	return TRUE;
+}
+
+void ControllerBackend_Deinit(void)
+{
+	glfwSetJoystickCallback(NULL);
+
+	joystick_connected = FALSE;
+	connected_joystick_id = 0;
+	joystick_neutral_x = 0;
+	joystick_neutral_y = 0;
+}
+
+BOOL ControllerBackend_GetJoystickStatus(JOYSTICK_STATUS *status)
+{
+	if (!joystick_connected)
+		return FALSE;
+
+	// Read axis
+	int total_axis;
+	const float *axis = glfwGetJoystickAxes(connected_joystick_id, &total_axis);
+
+	status->bLeft = axis[0] < joystick_neutral_x - DEADZONE;
+	status->bRight = axis[0] > joystick_neutral_x + DEADZONE;
+	status->bUp = axis[1] < joystick_neutral_y - DEADZONE;
+	status->bDown = axis[1] > joystick_neutral_y + DEADZONE;
+
+	// Read buttons
+	int total_buttons;
+	const unsigned char *buttons = glfwGetJoystickButtons(connected_joystick_id, &total_buttons);
+
+	// The original `Input.cpp` assumed there were 32 buttons (because of DirectInput's `DIJOYSTATE` struct)
+	if (total_buttons > 32)
+		total_buttons = 32;
+
+	// Read whatever buttons actually exist
+	for (int i = 0; i < total_buttons; ++i)
+		status->bButton[i] = buttons[i] == GLFW_PRESS;
+
+	// Blank the buttons that do not
+	for (int i = total_buttons; i < 32; ++i)
+		status->bButton[i] = FALSE;
+
+	return TRUE;
+}
+
+BOOL ControllerBackend_ResetJoystickStatus(void)
+{
+	if (!joystick_connected)
+		return FALSE;
+
+	// The code that would normally run here has been moved to JoystickCallback, to better-support hotplugging
+
+	return TRUE;
+}
--- /dev/null
+++ b/src/Backends/GLFW3/Misc.cpp
@@ -1,0 +1,292 @@
+#include "../Misc.h"
+
+#include <chrono>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <thread>
+
+#include <GLFW/glfw3.h>
+
+#include "../../WindowsWrapper.h"
+
+#include "Window.h"
+#include "../Rendering.h"
+#include "../../Main.h"
+#include "../../Organya.h"
+#include "../../Profile.h"
+#include "../../Resource.h"
+
+#define DO_KEY(GLFW_KEY, BACKEND_KEY) \
+	case GLFW_KEY: \
+		backend_keyboard_state[BACKEND_KEY] = action == GLFW_PRESS; \
+		break;
+
+BOOL bActive = TRUE;
+BOOL backend_keyboard_state[BACKEND_KEYBOARD_TOTAL];
+BOOL backend_previous_keyboard_state[BACKEND_KEYBOARD_TOTAL];
+
+static GLFWcursor* cursor;
+
+static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
+{
+	(void)window;
+	(void)scancode;
+	(void)mods;
+
+	switch (action)
+	{
+		case GLFW_RELEASE:
+		case GLFW_PRESS:
+			switch (key)
+			{
+				DO_KEY(GLFW_KEY_A, BACKEND_KEYBOARD_A)
+				DO_KEY(GLFW_KEY_B, BACKEND_KEYBOARD_B)
+				DO_KEY(GLFW_KEY_C, BACKEND_KEYBOARD_C)
+				DO_KEY(GLFW_KEY_D, BACKEND_KEYBOARD_D)
+				DO_KEY(GLFW_KEY_E, BACKEND_KEYBOARD_E)
+				DO_KEY(GLFW_KEY_F, BACKEND_KEYBOARD_F)
+				DO_KEY(GLFW_KEY_G, BACKEND_KEYBOARD_G)
+				DO_KEY(GLFW_KEY_H, BACKEND_KEYBOARD_H)
+				DO_KEY(GLFW_KEY_I, BACKEND_KEYBOARD_I)
+				DO_KEY(GLFW_KEY_J, BACKEND_KEYBOARD_J)
+				DO_KEY(GLFW_KEY_K, BACKEND_KEYBOARD_K)
+				DO_KEY(GLFW_KEY_L, BACKEND_KEYBOARD_L)
+				DO_KEY(GLFW_KEY_M, BACKEND_KEYBOARD_M)
+				DO_KEY(GLFW_KEY_N, BACKEND_KEYBOARD_N)
+				DO_KEY(GLFW_KEY_O, BACKEND_KEYBOARD_O)
+				DO_KEY(GLFW_KEY_P, BACKEND_KEYBOARD_P)
+				DO_KEY(GLFW_KEY_Q, BACKEND_KEYBOARD_Q)
+				DO_KEY(GLFW_KEY_R, BACKEND_KEYBOARD_R)
+				DO_KEY(GLFW_KEY_S, BACKEND_KEYBOARD_S)
+				DO_KEY(GLFW_KEY_T, BACKEND_KEYBOARD_T)
+				DO_KEY(GLFW_KEY_U, BACKEND_KEYBOARD_U)
+				DO_KEY(GLFW_KEY_V, BACKEND_KEYBOARD_V)
+				DO_KEY(GLFW_KEY_W, BACKEND_KEYBOARD_W)
+				DO_KEY(GLFW_KEY_X, BACKEND_KEYBOARD_X)
+				DO_KEY(GLFW_KEY_Y, BACKEND_KEYBOARD_Y)
+				DO_KEY(GLFW_KEY_Z, BACKEND_KEYBOARD_Z)
+				DO_KEY(GLFW_KEY_0, BACKEND_KEYBOARD_0)
+				DO_KEY(GLFW_KEY_1, BACKEND_KEYBOARD_1)
+				DO_KEY(GLFW_KEY_2, BACKEND_KEYBOARD_2)
+				DO_KEY(GLFW_KEY_3, BACKEND_KEYBOARD_3)
+				DO_KEY(GLFW_KEY_4, BACKEND_KEYBOARD_4)
+				DO_KEY(GLFW_KEY_5, BACKEND_KEYBOARD_5)
+				DO_KEY(GLFW_KEY_6, BACKEND_KEYBOARD_6)
+				DO_KEY(GLFW_KEY_7, BACKEND_KEYBOARD_7)
+				DO_KEY(GLFW_KEY_8, BACKEND_KEYBOARD_8)
+				DO_KEY(GLFW_KEY_9, BACKEND_KEYBOARD_9)
+				DO_KEY(GLFW_KEY_F1, BACKEND_KEYBOARD_F1)
+				DO_KEY(GLFW_KEY_F2, BACKEND_KEYBOARD_F2)
+				DO_KEY(GLFW_KEY_F3, BACKEND_KEYBOARD_F3)
+				DO_KEY(GLFW_KEY_F4, BACKEND_KEYBOARD_F4)
+				DO_KEY(GLFW_KEY_F5, BACKEND_KEYBOARD_F5)
+				DO_KEY(GLFW_KEY_F6, BACKEND_KEYBOARD_F6)
+				DO_KEY(GLFW_KEY_F7, BACKEND_KEYBOARD_F7)
+				DO_KEY(GLFW_KEY_F8, BACKEND_KEYBOARD_F8)
+				DO_KEY(GLFW_KEY_F9, BACKEND_KEYBOARD_F9)
+				DO_KEY(GLFW_KEY_F10, BACKEND_KEYBOARD_F10)
+				DO_KEY(GLFW_KEY_F11, BACKEND_KEYBOARD_F11)
+				DO_KEY(GLFW_KEY_F12, BACKEND_KEYBOARD_F12)
+				DO_KEY(GLFW_KEY_UP, BACKEND_KEYBOARD_UP)
+				DO_KEY(GLFW_KEY_DOWN, BACKEND_KEYBOARD_DOWN)
+				DO_KEY(GLFW_KEY_LEFT, BACKEND_KEYBOARD_LEFT)
+				DO_KEY(GLFW_KEY_RIGHT, BACKEND_KEYBOARD_RIGHT)
+				DO_KEY(GLFW_KEY_ESCAPE, BACKEND_KEYBOARD_ESCAPE)
+				DO_KEY(GLFW_KEY_GRAVE_ACCENT, BACKEND_KEYBOARD_BACK_QUOTE)
+				DO_KEY(GLFW_KEY_TAB, BACKEND_KEYBOARD_TAB)
+				DO_KEY(GLFW_KEY_CAPS_LOCK, BACKEND_KEYBOARD_CAPS_LOCK)
+				DO_KEY(GLFW_KEY_LEFT_SHIFT, BACKEND_KEYBOARD_LEFT_SHIFT)
+				DO_KEY(GLFW_KEY_LEFT_CONTROL, BACKEND_KEYBOARD_LEFT_CTRL)
+				DO_KEY(GLFW_KEY_LEFT_ALT, BACKEND_KEYBOARD_LEFT_ALT)
+				DO_KEY(GLFW_KEY_SPACE, BACKEND_KEYBOARD_SPACE)
+				DO_KEY(GLFW_KEY_RIGHT_ALT, BACKEND_KEYBOARD_RIGHT_ALT)
+				DO_KEY(GLFW_KEY_RIGHT_CONTROL, BACKEND_KEYBOARD_RIGHT_CTRL)
+				DO_KEY(GLFW_KEY_RIGHT_SHIFT, BACKEND_KEYBOARD_RIGHT_SHIFT)
+				DO_KEY(GLFW_KEY_ENTER, BACKEND_KEYBOARD_ENTER)
+				DO_KEY(GLFW_KEY_BACKSPACE, BACKEND_KEYBOARD_BACKSPACE)
+				DO_KEY(GLFW_KEY_MINUS, BACKEND_KEYBOARD_MINUS)
+				DO_KEY(GLFW_KEY_EQUAL, BACKEND_KEYBOARD_EQUALS)
+				DO_KEY(GLFW_KEY_LEFT_BRACKET, BACKEND_KEYBOARD_LEFT_BRACKET)
+				DO_KEY(GLFW_KEY_RIGHT_BRACKET, BACKEND_KEYBOARD_RIGHT_BRACKET)
+				DO_KEY(GLFW_KEY_BACKSLASH, BACKEND_KEYBOARD_BACK_SLASH)
+				DO_KEY(GLFW_KEY_SEMICOLON, BACKEND_KEYBOARD_SEMICOLON)
+				DO_KEY(GLFW_KEY_APOSTROPHE, BACKEND_KEYBOARD_APOSTROPHE)
+				DO_KEY(GLFW_KEY_COMMA, BACKEND_KEYBOARD_COMMA)
+				DO_KEY(GLFW_KEY_PERIOD, BACKEND_KEYBOARD_PERIOD)
+				DO_KEY(GLFW_KEY_SLASH, BACKEND_KEYBOARD_FORWARD_SLASH)
+
+				default:
+					break;
+			}
+
+			break;
+	}
+}
+
+static void WindowFocusCallback(GLFWwindow *window, int focused)
+{
+	(void)window;
+
+	if (focused)
+		ActiveWindow();
+	else
+		InactiveWindow();
+}
+
+static void WindowSizeCallback(GLFWwindow *window, int width, int height)
+{
+	(void)window;
+
+	RenderBackend_HandleWindowResize(width, height);
+}
+
+static void DragAndDropCallback(GLFWwindow *window, int count, const char **paths)
+{
+	(void)window;
+	(void)count;
+
+	LoadProfile(paths[0]);
+}
+
+void Backend_Init(void)
+{
+	glfwInit();
+}
+
+void Backend_Deinit(void)
+{
+	if (cursor != NULL)
+		glfwDestroyCursor(cursor);
+
+	glfwTerminate();
+}
+
+void Backend_PostWindowCreation(void)
+{
+	// Hook callbacks
+	glfwSetKeyCallback(window, KeyCallback);
+	glfwSetWindowFocusCallback(window, WindowFocusCallback);
+	glfwSetWindowSizeCallback(window, WindowSizeCallback);
+}
+
+BOOL Backend_GetBasePath(char *string_buffer)
+{
+	(void)string_buffer;
+
+	// GLFW3 doesn't seem to have a mechanism for this
+	return FALSE;
+}
+
+void Backend_HideMouse(void)
+{
+	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+}
+
+void Backend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
+{
+	// Convert to RGBA, since that's the only think GLFW3 accepts
+	unsigned char *rgba_pixels = (unsigned char*)malloc(width * height * 4);
+
+	const unsigned char *rgb_pointer = rgb_pixels;
+	unsigned char *rgba_pointer = rgba_pixels;
+
+	if (rgba_pixels != NULL)
+	{
+		for (unsigned int y = 0; y < height; ++y)
+		{
+			for (unsigned int x = 0; x < width; ++x)
+			{
+				*rgba_pointer++ = *rgb_pointer++;
+				*rgba_pointer++ = *rgb_pointer++;
+				*rgba_pointer++ = *rgb_pointer++;
+				*rgba_pointer++ = 0xFF;
+			}
+		}
+
+		GLFWimage glfw_image = {(int)width, (int)height, rgba_pixels};
+		glfwSetWindowIcon(window, 1, &glfw_image);
+
+		free(rgba_pixels);
+	}
+}
+
+void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
+{
+	// Convert to RGBA, since that's the only think GLFW3 accepts
+	unsigned char *rgba_pixels = (unsigned char*)malloc(width * height * 4);
+
+	const unsigned char *rgb_pointer = rgb_pixels;
+	unsigned char *rgba_pointer = rgba_pixels;
+
+	if (rgba_pixels != NULL)
+	{
+		for (unsigned int y = 0; y < height; ++y)
+		{
+			for (unsigned int x = 0; x < width; ++x)
+			{
+				if (rgb_pointer[0] == 0xFF && rgb_pointer[1] == 0 && rgb_pointer[2] == 0xFF)	// Colour-key
+				{
+					*rgba_pointer++ = *rgb_pointer++;
+					*rgba_pointer++ = *rgb_pointer++;
+					*rgba_pointer++ = *rgb_pointer++;
+					*rgba_pointer++ = 0;
+				}
+				else
+				{
+					*rgba_pointer++ = *rgb_pointer++;
+					*rgba_pointer++ = *rgb_pointer++;
+					*rgba_pointer++ = *rgb_pointer++;
+					*rgba_pointer++ = 0xFF;
+				}
+			}
+		}
+
+		GLFWimage glfw_image = {(int)width, (int)height, rgba_pixels};
+		cursor = glfwCreateCursor(&glfw_image, 0, 0);
+		glfwSetCursor(window, cursor);
+
+		free(rgba_pixels);
+	}
+}
+
+void PlaybackBackend_EnableDragAndDrop(void)
+{
+	glfwSetDropCallback(window, DragAndDropCallback);
+}
+
+BOOL Backend_SystemTask(void)
+{
+	if (glfwWindowShouldClose(window))
+	{
+		StopOrganyaMusic();
+		return FALSE;
+	}
+
+	memcpy(backend_previous_keyboard_state, backend_keyboard_state, sizeof(backend_keyboard_state));
+
+	glfwPollEvents();
+
+	while (!bActive)
+		glfwWaitEvents();
+
+	return TRUE;
+}
+
+void Backend_ShowMessageBox(const char *title, const char *message)
+{
+	// GLFW3 doesn't have a message box
+	printf("ShowMessageBox - '%s' - '%s'\n", title, message);
+}
+
+unsigned long Backend_GetTicks(void)
+{
+	return (unsigned long)(glfwGetTime() * 1000.0);
+}
+
+void Backend_Delay(unsigned int ticks)
+{
+	// GLFW3 doesn't have a delay function, so here's some butt-ugly C++11
+	std::this_thread::sleep_for(std::chrono::milliseconds(ticks));
+}
--- /dev/null
+++ b/src/Backends/GLFW3/Window-OpenGL3.cpp
@@ -1,0 +1,96 @@
+#include "../Window-OpenGL.h"
+#include "Window.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifdef USE_OPENGLES2
+#include <GLES2/gl2.h>
+#else
+#include <glad/glad.h>
+#endif
+#include <GLFW/glfw3.h>
+
+#include "../../WindowsWrapper.h"
+
+#include "../Misc.h"
+
+GLFWwindow *window;
+
+BOOL WindowBackend_OpenGL_CreateWindow(const char *window_title, int *screen_width, int *screen_height, BOOL fullscreen)
+{
+#ifdef USE_OPENGLES2
+	glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+#else
+	glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
+	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+#endif
+
+	GLFWmonitor *monitor = NULL;
+
+	if (fullscreen)
+	{
+		monitor = glfwGetPrimaryMonitor();
+
+		if (monitor != NULL)
+		{
+			const GLFWvidmode *mode = glfwGetVideoMode(monitor);
+
+			*screen_width = mode->width;
+			*screen_height = mode->height;
+		}
+	}
+
+	window = glfwCreateWindow(*screen_width, *screen_height, window_title, monitor, NULL);
+
+	if (window != NULL)
+	{
+		glfwMakeContextCurrent(window);
+
+			#ifndef USE_OPENGLES2
+				if (gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
+				{
+					// Check if the platform supports OpenGL 3.2
+					if (GLAD_GL_VERSION_3_2)
+					{
+			#endif
+						Backend_PostWindowCreation();
+
+						return TRUE;
+			#ifndef USE_OPENGLES2
+					}
+					else
+					{
+						Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Your system does not support OpenGL 3.2");
+					}
+				}
+				else
+				{
+					Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not load OpenGL functions");
+				}
+			#endif
+
+		glfwDestroyWindow(window);
+	}
+	else
+	{
+		Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not create window");
+	}
+
+	return FALSE;
+}
+
+void WindowBackend_OpenGL_DestroyWindow(void)
+{
+	glfwDestroyWindow(window);
+}
+
+void WindowBackend_OpenGL_Display(void)
+{
+	glfwSwapBuffers(window);
+}
--- /dev/null
+++ b/src/Backends/GLFW3/Window-OpenGLES2.cpp
@@ -1,0 +1,2 @@
+#define USE_OPENGLES2
+#include "Window-OpenGL3.cpp"
--- /dev/null
+++ b/src/Backends/GLFW3/Window.h
@@ -1,0 +1,7 @@
+#pragma once
+
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+#undef GLFW_INCLUDE_NONE
+
+extern GLFWwindow *window;
--- /dev/null
+++ b/src/Backends/Misc.h
@@ -1,0 +1,101 @@
+#pragma once
+
+#include "../WindowsWrapper.h"
+
+enum
+{
+	// Based on US QWERTY
+	BACKEND_KEYBOARD_A,
+	BACKEND_KEYBOARD_B,
+	BACKEND_KEYBOARD_C,
+	BACKEND_KEYBOARD_D,
+	BACKEND_KEYBOARD_E,
+	BACKEND_KEYBOARD_F,
+	BACKEND_KEYBOARD_G,
+	BACKEND_KEYBOARD_H,
+	BACKEND_KEYBOARD_I,
+	BACKEND_KEYBOARD_J,
+	BACKEND_KEYBOARD_K,
+	BACKEND_KEYBOARD_L,
+	BACKEND_KEYBOARD_M,
+	BACKEND_KEYBOARD_N,
+	BACKEND_KEYBOARD_O,
+	BACKEND_KEYBOARD_P,
+	BACKEND_KEYBOARD_Q,
+	BACKEND_KEYBOARD_R,
+	BACKEND_KEYBOARD_S,
+	BACKEND_KEYBOARD_T,
+	BACKEND_KEYBOARD_U,
+	BACKEND_KEYBOARD_V,
+	BACKEND_KEYBOARD_W,
+	BACKEND_KEYBOARD_X,
+	BACKEND_KEYBOARD_Y,
+	BACKEND_KEYBOARD_Z,
+	BACKEND_KEYBOARD_0,
+	BACKEND_KEYBOARD_1,
+	BACKEND_KEYBOARD_2,
+	BACKEND_KEYBOARD_3,
+	BACKEND_KEYBOARD_4,
+	BACKEND_KEYBOARD_5,
+	BACKEND_KEYBOARD_6,
+	BACKEND_KEYBOARD_7,
+	BACKEND_KEYBOARD_8,
+	BACKEND_KEYBOARD_9,
+	BACKEND_KEYBOARD_F1,
+	BACKEND_KEYBOARD_F2,
+	BACKEND_KEYBOARD_F3,
+	BACKEND_KEYBOARD_F4,
+	BACKEND_KEYBOARD_F5,
+	BACKEND_KEYBOARD_F6,
+	BACKEND_KEYBOARD_F7,
+	BACKEND_KEYBOARD_F8,
+	BACKEND_KEYBOARD_F9,
+	BACKEND_KEYBOARD_F10,
+	BACKEND_KEYBOARD_F11,
+	BACKEND_KEYBOARD_F12,
+	BACKEND_KEYBOARD_UP,
+	BACKEND_KEYBOARD_DOWN,
+	BACKEND_KEYBOARD_LEFT,
+	BACKEND_KEYBOARD_RIGHT,
+	BACKEND_KEYBOARD_ESCAPE,
+	BACKEND_KEYBOARD_BACK_QUOTE,
+	BACKEND_KEYBOARD_TAB,
+	BACKEND_KEYBOARD_CAPS_LOCK,
+	BACKEND_KEYBOARD_LEFT_SHIFT,
+	BACKEND_KEYBOARD_LEFT_CTRL,
+	BACKEND_KEYBOARD_LEFT_ALT,
+	BACKEND_KEYBOARD_SPACE,
+	BACKEND_KEYBOARD_RIGHT_ALT,
+	BACKEND_KEYBOARD_RIGHT_CTRL,
+	BACKEND_KEYBOARD_RIGHT_SHIFT,
+	BACKEND_KEYBOARD_ENTER,
+	BACKEND_KEYBOARD_BACKSPACE,
+	BACKEND_KEYBOARD_MINUS,
+	BACKEND_KEYBOARD_EQUALS,
+	BACKEND_KEYBOARD_LEFT_BRACKET,
+	BACKEND_KEYBOARD_RIGHT_BRACKET,
+	BACKEND_KEYBOARD_BACK_SLASH,
+	BACKEND_KEYBOARD_SEMICOLON,
+	BACKEND_KEYBOARD_APOSTROPHE,
+	BACKEND_KEYBOARD_COMMA,
+	BACKEND_KEYBOARD_PERIOD,
+	BACKEND_KEYBOARD_FORWARD_SLASH,
+	BACKEND_KEYBOARD_TOTAL
+};
+
+extern BOOL bActive;
+extern BOOL backend_keyboard_state[BACKEND_KEYBOARD_TOTAL];
+extern BOOL backend_previous_keyboard_state[BACKEND_KEYBOARD_TOTAL];
+
+void Backend_Init(void);
+void Backend_Deinit(void);
+void Backend_PostWindowCreation(void);
+BOOL Backend_GetBasePath(char *string_buffer);
+void Backend_HideMouse(void);
+void Backend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, unsigned int height);
+void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height);
+void PlaybackBackend_EnableDragAndDrop(void);
+BOOL Backend_SystemTask(void);
+void Backend_ShowMessageBox(const char *title, const char *message);
+unsigned long Backend_GetTicks(void);
+void Backend_Delay(unsigned int ticks);
--- a/src/Backends/Platform.h
+++ /dev/null
@@ -1,18 +1,0 @@
-#pragma once
-
-#include "../WindowsWrapper.h"
-
-extern BOOL bActive;
-
-void PlatformBackend_Init(void);
-void PlatformBackend_Deinit(void);
-void PlatformBackend_PostWindowCreation(void);
-BOOL PlatformBackend_GetBasePath(char *string_buffer);
-void PlatformBackend_HideMouse(void);
-void PlatformBackend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, unsigned int height);
-void PlatformBackend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height);
-void PlaybackBackend_EnableDragAndDrop(void);
-BOOL PlatformBackend_SystemTask(void);
-void PlatformBackend_ShowMessageBox(const char *title, const char *message);
-unsigned long PlatformBackend_GetTicks(void);
-void PlatformBackend_Delay(unsigned int ticks);
--- a/src/Backends/Platform/GLFW3.cpp
+++ /dev/null
@@ -1,367 +1,0 @@
-#include "../Platform.h"
-
-#include <chrono>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <thread>
-
-#include <GLFW/glfw3.h>
-
-#include "../Rendering.h"
-
-#include "../../WindowsWrapper.h"
-
-#include "../../KeyControl.h"
-#include "../../Main.h"
-#include "../../Organya.h"
-#include "../../Profile.h"
-#include "../../Resource.h"
-
-GLFWwindow *window;
-
-BOOL bActive = TRUE;
-
-static GLFWcursor* cursor;
-
-static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
-{
-	(void)window;
-	(void)scancode;
-	(void)mods;
-
-	switch (action)
-	{
-		case GLFW_PRESS:
-			switch (key)
-			{
-				case GLFW_KEY_ESCAPE:
-					gKey |= KEY_ESCAPE;
-					break;
-
-				case GLFW_KEY_W:
-					gKey |= KEY_MAP;
-					break;
-
-				case GLFW_KEY_LEFT:
-					gKey |= KEY_LEFT;
-					break;
-
-				case GLFW_KEY_RIGHT:
-					gKey |= KEY_RIGHT;
-					break;
-
-				case GLFW_KEY_UP:
-					gKey |= KEY_UP;
-					break;
-
-				case GLFW_KEY_DOWN:
-					gKey |= KEY_DOWN;
-					break;
-
-				case GLFW_KEY_X:
-					gKey |= KEY_X;
-					break;
-
-				case GLFW_KEY_Z:
-					gKey |= KEY_Z;
-					break;
-
-				case GLFW_KEY_S:
-					gKey |= KEY_ARMS;
-					break;
-
-				case GLFW_KEY_A:
-					gKey |= KEY_ARMSREV;
-					break;
-
-				case GLFW_KEY_LEFT_SHIFT:
-				case GLFW_KEY_RIGHT_SHIFT:
-					gKey |= KEY_SHIFT;
-					break;
-
-				case GLFW_KEY_F1:
-					gKey |= KEY_F1;
-					break;
-
-				case GLFW_KEY_F2:
-					gKey |= KEY_F2;
-					break;
-
-				case GLFW_KEY_Q:
-					gKey |= KEY_ITEM;
-					break;
-
-				case GLFW_KEY_COMMA:
-					gKey |= KEY_ALT_LEFT;
-					break;
-
-				case GLFW_KEY_PERIOD:
-					gKey |= KEY_ALT_DOWN;
-					break;
-
-				case GLFW_KEY_SLASH:
-					gKey |= KEY_ALT_RIGHT;
-					break;
-
-				case GLFW_KEY_L:
-					gKey |= KEY_L;
-					break;
-
-				case GLFW_KEY_EQUAL:
-					gKey |= KEY_PLUS;
-					break;
-
-				case GLFW_KEY_F5:
-					gbUseJoystick = FALSE;
-					break;
-			}
-
-			break;
-
-		case GLFW_RELEASE:
-			switch (key)
-			{
-				case GLFW_KEY_ESCAPE:
-					gKey &= ~KEY_ESCAPE;
-					break;
-
-				case GLFW_KEY_W:
-					gKey &= ~KEY_MAP;
-					break;
-
-				case GLFW_KEY_LEFT:
-					gKey &= ~KEY_LEFT;
-					break;
-
-				case GLFW_KEY_RIGHT:
-					gKey &= ~KEY_RIGHT;
-					break;
-
-				case GLFW_KEY_UP:
-					gKey &= ~KEY_UP;
-					break;
-
-				case GLFW_KEY_DOWN:
-					gKey &= ~KEY_DOWN;
-					break;
-
-				case GLFW_KEY_X:
-					gKey &= ~KEY_X;
-					break;
-
-				case GLFW_KEY_Z:
-					gKey &= ~KEY_Z;
-					break;
-
-				case GLFW_KEY_S:
-					gKey &= ~KEY_ARMS;
-					break;
-
-				case GLFW_KEY_A:
-					gKey &= ~KEY_ARMSREV;
-					break;
-
-				case GLFW_KEY_LEFT_SHIFT:
-				case GLFW_KEY_RIGHT_SHIFT:
-					gKey &= ~KEY_SHIFT;
-					break;
-
-				case GLFW_KEY_F1:
-					gKey &= ~KEY_F1;
-					break;
-
-				case GLFW_KEY_F2:
-					gKey &= ~KEY_F2;
-					break;
-
-				case GLFW_KEY_Q:
-					gKey &= ~KEY_ITEM;
-					break;
-
-				case GLFW_KEY_COMMA:
-					gKey &= ~KEY_ALT_LEFT;
-					break;
-
-				case GLFW_KEY_PERIOD:
-					gKey &= ~KEY_ALT_DOWN;
-					break;
-
-				case GLFW_KEY_SLASH:
-					gKey &= ~KEY_ALT_RIGHT;
-					break;
-
-				case GLFW_KEY_L:
-					gKey &= ~KEY_L;
-					break;
-
-				case GLFW_KEY_EQUAL:
-					gKey &= ~KEY_PLUS;
-					break;
-			}
-
-			break;
-	}
-}
-
-static void WindowFocusCallback(GLFWwindow *window, int focused)
-{
-	(void)window;
-
-	if (focused)
-		ActiveWindow();
-	else
-		InactiveWindow();
-}
-
-static void WindowSizeCallback(GLFWwindow *window, int width, int height)
-{
-	(void)window;
-
-	Backend_HandleWindowResize(width, height);
-}
-
-static void DragAndDropCallback(GLFWwindow *window, int count, const char **paths)
-{
-	(void)window;
-	(void)count;
-
-	LoadProfile(paths[0]);
-}
-
-void PlatformBackend_Init(void)
-{
-	glfwInit();
-}
-
-void PlatformBackend_Deinit(void)
-{
-	if (cursor != NULL)
-		glfwDestroyCursor(cursor);
-
-	glfwTerminate();
-}
-
-void PlatformBackend_PostWindowCreation(void)
-{
-	// Hook callbacks
-	glfwSetKeyCallback(window, KeyCallback);
-	glfwSetWindowFocusCallback(window, WindowFocusCallback);
-	glfwSetWindowSizeCallback(window, WindowSizeCallback);
-}
-
-BOOL PlatformBackend_GetBasePath(char *string_buffer)
-{
-	// GLFW3 doesn't seem to have a mechanism for this
-	return FALSE;
-}
-
-void PlatformBackend_HideMouse(void)
-{
-	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
-}
-
-void PlatformBackend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
-{
-	// Convert to RGBA, since that's the only think GLFW3 accepts
-	unsigned char *rgba_pixels = (unsigned char*)malloc(width * height * 4);
-
-	const unsigned char *rgb_pointer = rgb_pixels;
-	unsigned char *rgba_pointer = rgba_pixels;
-
-	if (rgba_pixels != NULL)
-	{
-		for (unsigned int y = 0; y < height; ++y)
-		{
-			for (unsigned int x = 0; x < width; ++x)
-			{
-				*rgba_pointer++ = *rgb_pointer++;
-				*rgba_pointer++ = *rgb_pointer++;
-				*rgba_pointer++ = *rgb_pointer++;
-				*rgba_pointer++ = 0xFF;
-			}
-		}
-
-		GLFWimage glfw_image = {(int)width, (int)height, rgba_pixels};
-		glfwSetWindowIcon(window, 1, &glfw_image);
-
-		free(rgba_pixels);
-	}
-}
-
-void PlatformBackend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
-{
-	// Convert to RGBA, since that's the only think GLFW3 accepts
-	unsigned char *rgba_pixels = (unsigned char*)malloc(width * height * 4);
-
-	const unsigned char *rgb_pointer = rgb_pixels;
-	unsigned char *rgba_pointer = rgba_pixels;
-
-	if (rgba_pixels != NULL)
-	{
-		for (unsigned int y = 0; y < height; ++y)
-		{
-			for (unsigned int x = 0; x < width; ++x)
-			{
-				if (rgb_pointer[0] == 0xFF && rgb_pointer[1] == 0 && rgb_pointer[2] == 0xFF)	// Colour-key
-				{
-					*rgba_pointer++ = *rgb_pointer++;
-					*rgba_pointer++ = *rgb_pointer++;
-					*rgba_pointer++ = *rgb_pointer++;
-					*rgba_pointer++ = 0;
-				}
-				else
-				{
-					*rgba_pointer++ = *rgb_pointer++;
-					*rgba_pointer++ = *rgb_pointer++;
-					*rgba_pointer++ = *rgb_pointer++;
-					*rgba_pointer++ = 0xFF;
-				}
-			}
-		}
-
-		GLFWimage glfw_image = {(int)width, (int)height, rgba_pixels};
-		cursor = glfwCreateCursor(&glfw_image, 0, 0);
-		glfwSetCursor(window, cursor);
-
-		free(rgba_pixels);
-	}
-}
-
-void PlaybackBackend_EnableDragAndDrop(void)
-{
-	glfwSetDropCallback(window, DragAndDropCallback);
-}
-
-BOOL PlatformBackend_SystemTask(void)
-{
-	if (glfwWindowShouldClose(window))
-	{
-		StopOrganyaMusic();
-		return FALSE;
-	}
-
-	glfwPollEvents();
-
-	while (!bActive)
-		glfwWaitEvents();
-
-	return TRUE;
-}
-
-void PlatformBackend_ShowMessageBox(const char *title, const char *message)
-{
-	// GLFW3 doesn't have a message box
-	printf("ShowMessageBox - '%s' - '%s'\n", title, message);
-}
-
-unsigned long PlatformBackend_GetTicks(void)
-{
-	return (unsigned long)(glfwGetTime() * 1000.0);
-}
-
-void PlatformBackend_Delay(unsigned int ticks)
-{
-	// GLFW3 doesn't have a delay function, so here's some butt-ugly C++11
-	std::this_thread::sleep_for(std::chrono::milliseconds(ticks));
-}
--- a/src/Backends/Platform/SDL2.cpp
+++ /dev/null
@@ -1,325 +1,0 @@
-#include "../Platform.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "SDL.h"
-
-#include "../Rendering.h"
-
-#include "../../WindowsWrapper.h"
-
-#include "../../KeyControl.h"
-#include "../../Main.h"
-#include "../../Organya.h"
-#include "../../Profile.h"
-#include "../../Resource.h"
-
-SDL_Window *window;
-
-BOOL bActive = TRUE;
-
-static SDL_Surface *cursor_surface;
-static SDL_Cursor *cursor;
-
-void PlatformBackend_Init(void)
-{
-	SDL_Init(SDL_INIT_EVENTS);
-
-	SDL_InitSubSystem(SDL_INIT_VIDEO);
-
-	puts("Available SDL2 video drivers:");
-
-	for (int i = 0; i < SDL_GetNumVideoDrivers(); ++i)
-		puts(SDL_GetVideoDriver(i));
-
-	printf("Selected SDL2 video driver: %s\n", SDL_GetCurrentVideoDriver());
-}
-
-void PlatformBackend_Deinit(void)
-{
-	if (cursor != NULL)
-		SDL_FreeCursor(cursor);
-
-	if (cursor_surface != NULL)
-		SDL_FreeSurface(cursor_surface);
-
-	SDL_Quit();
-}
-
-void PlatformBackend_PostWindowCreation(void)
-{
-	
-}
-
-BOOL PlatformBackend_GetBasePath(char *string_buffer)
-{
-	char *base_path = SDL_GetBasePath();
-	// Trim the trailing '/'
-	size_t base_path_length = strlen(base_path);
-	base_path[base_path_length - 1] = '\0';
-	strcpy(string_buffer, base_path);
-	SDL_free(base_path);
-
-	return TRUE;
-}
-
-void PlatformBackend_HideMouse(void)
-{
-	SDL_ShowCursor(SDL_DISABLE);
-}
-
-void PlatformBackend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
-{
-	SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormatFrom((void*)rgb_pixels, width, height, 0, width * 3, SDL_PIXELFORMAT_RGB24);
-	SDL_SetWindowIcon(window, surface);
-	SDL_FreeSurface(surface);
-}
-
-void PlatformBackend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
-{
-	cursor_surface = SDL_CreateRGBSurfaceWithFormatFrom((void*)rgb_pixels, width, height, 0, width * 3, SDL_PIXELFORMAT_RGB24);
-	SDL_SetColorKey(cursor_surface, SDL_TRUE, SDL_MapRGB(cursor_surface->format, 0xFF, 0, 0xFF));
-	cursor = SDL_CreateColorCursor(cursor_surface, 0, 0);
-	SDL_SetCursor(cursor);
-}
-
-void PlaybackBackend_EnableDragAndDrop(void)
-{
-	SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
-}
-
-BOOL PlatformBackend_SystemTask(void)
-{
-	while (SDL_PollEvent(NULL) || !bActive)
-	{
-		SDL_Event event;
-
-		if (!SDL_WaitEvent(&event))
-			return FALSE;
-
-		switch (event.type)
-		{
-			case SDL_KEYDOWN:
-				switch (event.key.keysym.sym)
-				{
-					case SDLK_ESCAPE:
-						gKey |= KEY_ESCAPE;
-						break;
-
-					case SDLK_w:
-						gKey |= KEY_MAP;
-						break;
-
-					case SDLK_LEFT:
-						gKey |= KEY_LEFT;
-						break;
-
-					case SDLK_RIGHT:
-						gKey |= KEY_RIGHT;
-						break;
-
-					case SDLK_UP:
-						gKey |= KEY_UP;
-						break;
-
-					case SDLK_DOWN:
-						gKey |= KEY_DOWN;
-						break;
-
-					case SDLK_x:
-						gKey |= KEY_X;
-						break;
-
-					case SDLK_z:
-						gKey |= KEY_Z;
-						break;
-
-					case SDLK_s:
-						gKey |= KEY_ARMS;
-						break;
-
-					case SDLK_a:
-						gKey |= KEY_ARMSREV;
-						break;
-
-					case SDLK_LSHIFT:
-					case SDLK_RSHIFT:
-						gKey |= KEY_SHIFT;
-						break;
-
-					case SDLK_F1:
-						gKey |= KEY_F1;
-						break;
-
-					case SDLK_F2:
-						gKey |= KEY_F2;
-						break;
-
-					case SDLK_q:
-						gKey |= KEY_ITEM;
-						break;
-
-					case SDLK_COMMA:
-						gKey |= KEY_ALT_LEFT;
-						break;
-
-					case SDLK_PERIOD:
-						gKey |= KEY_ALT_DOWN;
-						break;
-
-					case SDLK_SLASH:
-						gKey |= KEY_ALT_RIGHT;
-						break;
-
-					case SDLK_l:
-						gKey |= KEY_L;
-						break;
-
-					case SDLK_PLUS:
-						gKey |= KEY_PLUS;
-						break;
-
-					case SDLK_F5:
-						gbUseJoystick = FALSE;
-						break;
-				}
-
-				break;
-
-			case SDL_KEYUP:
-				switch (event.key.keysym.sym)
-				{
-					case SDLK_ESCAPE:
-						gKey &= ~KEY_ESCAPE;
-						break;
-
-					case SDLK_w:
-						gKey &= ~KEY_MAP;
-						break;
-
-					case SDLK_LEFT:
-						gKey &= ~KEY_LEFT;
-						break;
-
-					case SDLK_RIGHT:
-						gKey &= ~KEY_RIGHT;
-						break;
-
-					case SDLK_UP:
-						gKey &= ~KEY_UP;
-						break;
-
-					case SDLK_DOWN:
-						gKey &= ~KEY_DOWN;
-						break;
-
-					case SDLK_x:
-						gKey &= ~KEY_X;
-						break;
-
-					case SDLK_z:
-						gKey &= ~KEY_Z;
-						break;
-
-					case SDLK_s:
-						gKey &= ~KEY_ARMS;
-						break;
-
-					case SDLK_a:
-						gKey &= ~KEY_ARMSREV;
-						break;
-
-					case SDLK_LSHIFT:
-					case SDLK_RSHIFT:
-						gKey &= ~KEY_SHIFT;
-						break;
-
-					case SDLK_F1:
-						gKey &= ~KEY_F1;
-						break;
-
-					case SDLK_F2:
-						gKey &= ~KEY_F2;
-						break;
-
-					case SDLK_q:
-						gKey &= ~KEY_ITEM;
-						break;
-
-					case SDLK_COMMA:
-						gKey &= ~KEY_ALT_LEFT;
-						break;
-
-					case SDLK_PERIOD:
-						gKey &= ~KEY_ALT_DOWN;
-						break;
-
-					case SDLK_SLASH:
-						gKey &= ~KEY_ALT_RIGHT;
-						break;
-
-					case SDLK_l:
-						gKey &= ~KEY_L;
-						break;
-
-					case SDLK_PLUS:
-						gKey &= ~KEY_PLUS;
-						break;
-				}
-
-				break;
-
-			case SDL_DROPFILE:
-				LoadProfile(event.drop.file);
-				SDL_free(event.drop.file);
-				break;
-
-			case SDL_WINDOWEVENT:
-				switch (event.window.event)
-				{
-					case SDL_WINDOWEVENT_FOCUS_LOST:
-						InactiveWindow();
-						break;
-
-					case SDL_WINDOWEVENT_FOCUS_GAINED:
-						ActiveWindow();
-						break;
-
-					case SDL_WINDOWEVENT_RESIZED:
-					case SDL_WINDOWEVENT_SIZE_CHANGED:
-						Backend_HandleWindowResize(event.window.data1, event.window.data2);
-						break;
-				}
-
-				break;
-
-			case SDL_QUIT:
-				StopOrganyaMusic();
-				return FALSE;
-
-			case SDL_RENDER_TARGETS_RESET:
-				Backend_HandleRenderTargetLoss();
-				break;
-
-		}
-	}
-
-	return TRUE;
-}
-
-void PlatformBackend_ShowMessageBox(const char *title, const char *message)
-{
-	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, window);
-}
-
-unsigned long PlatformBackend_GetTicks(void)
-{
-	return SDL_GetTicks();
-}
-
-void PlatformBackend_Delay(unsigned int ticks)
-{
-	SDL_Delay(ticks);
-}
--- a/src/Backends/Rendering.h
+++ b/src/Backends/Rendering.h
@@ -2,25 +2,25 @@
 
 #include "../WindowsWrapper.h"
 
-typedef struct Backend_Surface Backend_Surface;
-typedef struct Backend_Glyph Backend_Glyph;
+typedef struct RenderBackend_Surface RenderBackend_Surface;
+typedef struct RenderBackend_Glyph RenderBackend_Glyph;
 
-Backend_Surface* Backend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen);
-void Backend_Deinit(void);
-void Backend_DrawScreen(void);
-void Backend_ClearScreen(void);
-Backend_Surface* Backend_CreateSurface(unsigned int width, unsigned int height);
-void Backend_FreeSurface(Backend_Surface *surface);
-BOOL Backend_IsSurfaceLost(Backend_Surface *surface);
-void Backend_RestoreSurface(Backend_Surface *surface);
-unsigned char* Backend_LockSurface(Backend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height);
-void Backend_UnlockSurface(Backend_Surface *surface, unsigned int width, unsigned int height);
-void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key);
-void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue);
-Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch);
-void Backend_UnloadGlyph(Backend_Glyph *glyph);
-void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels);
-void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y);
-void Backend_FlushGlyphs(void);
-void Backend_HandleRenderTargetLoss(void);
-void Backend_HandleWindowResize(unsigned int width, unsigned int height);
+RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen);
+void RenderBackend_Deinit(void);
+void RenderBackend_DrawScreen(void);
+void RenderBackend_ClearScreen(void);
+RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height);
+void RenderBackend_FreeSurface(RenderBackend_Surface *surface);
+BOOL RenderBackend_IsSurfaceLost(RenderBackend_Surface *surface);
+void RenderBackend_RestoreSurface(RenderBackend_Surface *surface);
+unsigned char* RenderBackend_LockSurface(RenderBackend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height);
+void RenderBackend_UnlockSurface(RenderBackend_Surface *surface, unsigned int width, unsigned int height);
+void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RECT *rect, RenderBackend_Surface *destination_surface, long x, long y, BOOL colour_key);
+void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue);
+RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch);
+void RenderBackend_UnloadGlyph(RenderBackend_Glyph *glyph);
+void RenderBackend_PrepareToDrawGlyphs(RenderBackend_Surface *destination_surface, const unsigned char *colour_channels);
+void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y);
+void RenderBackend_FlushGlyphs(void);
+void RenderBackend_HandleRenderTargetLoss(void);
+void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height);
--- a/src/Backends/Rendering/OpenGL3.cpp
+++ b/src/Backends/Rendering/OpenGL3.cpp
@@ -10,7 +10,7 @@
 #ifdef USE_OPENGLES2
 #include <GLES2/gl2.h>
 #else
-#include "../../../external/glad/include/glad/glad.h"
+#include <glad/glad.h>
 #endif
 
 #define SPRITEBATCH_IMPLEMENTATION
@@ -18,8 +18,8 @@
 
 #include "../../WindowsWrapper.h"
 
-#include "../Platform.h"
-#include "../Window.h"
+#include "../Misc.h"
+#include "../Window-OpenGL.h"
 #include "../../Resource.h"
 
 #define TOTAL_VBOS 8
@@ -36,21 +36,21 @@
 	MODE_DRAW_GLYPH
 } RenderMode;
 
-typedef struct Backend_Surface
+typedef struct RenderBackend_Surface
 {
 	GLuint texture_id;
 	unsigned int width;
 	unsigned int height;
 	unsigned char *pixels;
-} Backend_Surface;
+} RenderBackend_Surface;
 
-typedef struct Backend_Glyph
+typedef struct RenderBackend_Glyph
 {
 	unsigned char *pixels;
 	unsigned int width;
 	unsigned int height;
 	unsigned int pitch;
-} Backend_Glyph;
+} RenderBackend_Glyph;
 
 typedef struct Coordinate2D
 {
@@ -91,10 +91,10 @@
 static GLuint last_source_texture;
 static GLuint last_destination_texture;
 
-static Backend_Surface framebuffer;
+static RenderBackend_Surface framebuffer;
 
 static unsigned char glyph_colour_channels[3];
-static Backend_Surface *glyph_destination_surface;
+static RenderBackend_Surface *glyph_destination_surface;
 
 static spritebatch_t glyph_batcher;
 
@@ -275,7 +275,7 @@
 	{
 		char buffer[0x200];
 		glGetShaderInfoLog(vertex_shader, sizeof(buffer), NULL, buffer);
-		PlatformBackend_ShowMessageBox("Vertex shader error", buffer);
+		Backend_ShowMessageBox("Vertex shader error", buffer);
 		return 0;
 	}
 
@@ -291,7 +291,7 @@
 	{
 		char buffer[0x200];
 		glGetShaderInfoLog(fragment_shader, sizeof(buffer), NULL, buffer);
-		PlatformBackend_ShowMessageBox("Fragment shader error", buffer);
+		Backend_ShowMessageBox("Fragment shader error", buffer);
 		return 0;
 	}
 
@@ -308,7 +308,7 @@
 	{
 		char buffer[0x200];
 		glGetProgramInfoLog(program_id, sizeof(buffer), NULL, buffer);
-		PlatformBackend_ShowMessageBox("Shader linker error", buffer);
+		Backend_ShowMessageBox("Shader linker error", buffer);
 		return 0;
 	}
 
@@ -380,6 +380,7 @@
 	static unsigned char last_green;
 	static unsigned char last_blue;
 
+	(void)texture_h;
 	(void)udata;
 
 	if (glyph_destination_surface == NULL)
@@ -419,7 +420,7 @@
 
 	for (int i = 0; i < count; ++i)
 	{
-		Backend_Glyph *glyph = (Backend_Glyph*)sprites[i].image_id;
+		RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)sprites[i].image_id;
 
 		const GLfloat texture_left = sprites[i].minx;
 		const GLfloat texture_right = texture_left + ((GLfloat)glyph->width / (GLfloat)texture_w);	// Account for width not matching pitch
@@ -466,7 +467,7 @@
 {
 	(void)udata;
 
-	Backend_Glyph *glyph = (Backend_Glyph*)image_id;
+	RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)image_id;
 
 	memcpy(buffer, glyph->pixels, bytes_to_fill);
 }
@@ -516,7 +517,7 @@
 // Render-backend initialisation
 // ====================
 
-Backend_Surface* Backend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
+RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
 {
 	actual_screen_width = screen_width;
 	actual_screen_height = screen_height;
@@ -623,7 +624,7 @@
 	return NULL;
 }
 
-void Backend_Deinit(void)
+void RenderBackend_Deinit(void)
 {
 	free(local_vertex_buffer);
 
@@ -643,7 +644,7 @@
 	WindowBackend_OpenGL_DestroyWindow();
 }
 
-void Backend_DrawScreen(void)
+void RenderBackend_DrawScreen(void)
 {
 	spritebatch_tick(&glyph_batcher);
 
@@ -736,9 +737,9 @@
 // Surface management
 // ====================
 
-Backend_Surface* Backend_CreateSurface(unsigned int width, unsigned int height)
+RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height)
 {
-	Backend_Surface *surface = (Backend_Surface*)malloc(sizeof(Backend_Surface));
+	RenderBackend_Surface *surface = (RenderBackend_Surface*)malloc(sizeof(RenderBackend_Surface));
 
 	if (surface == NULL)
 		return NULL;
@@ -766,7 +767,7 @@
 	return surface;
 }
 
-void Backend_FreeSurface(Backend_Surface *surface)
+void RenderBackend_FreeSurface(RenderBackend_Surface *surface)
 {
 	if (surface == NULL)
 		return;
@@ -779,7 +780,7 @@
 	free(surface);
 }
 
-BOOL Backend_IsSurfaceLost(Backend_Surface *surface)
+BOOL RenderBackend_IsSurfaceLost(RenderBackend_Surface *surface)
 {
 	(void)surface;
 
@@ -786,12 +787,12 @@
 	return FALSE;
 }
 
-void Backend_RestoreSurface(Backend_Surface *surface)
+void RenderBackend_RestoreSurface(RenderBackend_Surface *surface)
 {
 	(void)surface;
 }
 
-unsigned char* Backend_LockSurface(Backend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
+unsigned char* RenderBackend_LockSurface(RenderBackend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
 {
 	if (surface == NULL)
 		return NULL;
@@ -801,7 +802,7 @@
 	return surface->pixels;
 }
 
-void Backend_UnlockSurface(Backend_Surface *surface, unsigned int width, unsigned int height)
+void RenderBackend_UnlockSurface(RenderBackend_Surface *surface, unsigned int width, unsigned int height)
 {
 	if (surface == NULL)
 		return;
@@ -821,7 +822,7 @@
 // Drawing
 // ====================
 
-void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
+void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RECT *rect, RenderBackend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
 	if (source_surface == NULL || destination_surface == NULL)
 		return;
@@ -897,7 +898,7 @@
 	vertex_buffer_slot->vertices[1][2].vertex_coordinate.y = vertex_bottom;
 }
 
-void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
+void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
 	static unsigned char last_red;
 	static unsigned char last_green;
@@ -962,9 +963,9 @@
 // Glyph management
 // ====================
 
-Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
+RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
 {
-	Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
+	RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)malloc(sizeof(RenderBackend_Glyph));
 
 	if (glyph != NULL)
 	{
@@ -993,7 +994,7 @@
 	return NULL;
 }
 
-void Backend_UnloadGlyph(Backend_Glyph *glyph)
+void RenderBackend_UnloadGlyph(RenderBackend_Glyph *glyph)
 {
 	if (glyph == NULL)
 		return;
@@ -1002,7 +1003,7 @@
 	free(glyph);
 }
 
-void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
+void RenderBackend_PrepareToDrawGlyphs(RenderBackend_Surface *destination_surface, const unsigned char *colour_channels)
 {
 	glyph_destination_surface = destination_surface;
 
@@ -1009,12 +1010,12 @@
 	memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
 }
 
-void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
+void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y)
 {
 	spritebatch_push(&glyph_batcher, (SPRITEBATCH_U64)glyph, glyph->pitch, glyph->height, x, y, 1.0f, 1.0f, 0.0f, 0.0f, 0);
 }
 
-void Backend_FlushGlyphs(void)
+void RenderBackend_FlushGlyphs(void)
 {
 	spritebatch_defrag(&glyph_batcher);
 	spritebatch_flush(&glyph_batcher);
@@ -1024,12 +1025,12 @@
 // Misc.
 // ====================
 
-void Backend_HandleRenderTargetLoss(void)
+void RenderBackend_HandleRenderTargetLoss(void)
 {
 	// No problem for us
 }
 
-void Backend_HandleWindowResize(unsigned int width, unsigned int height)
+void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height)
 {
 	actual_screen_width = width;
 	actual_screen_height = height;
--- a/src/Backends/Rendering/SDLSurface.cpp
+++ b/src/Backends/Rendering/SDLSurface.cpp
@@ -8,23 +8,24 @@
 
 #include "../../WindowsWrapper.h"
 
-#include "../Platform.h"
+#include "../Misc.h"
+#include "../SDL2/Window.h"
 
-typedef struct Backend_Surface
+typedef struct RenderBackend_Surface
 {
 	SDL_Surface *sdlsurface;
-} Backend_Surface;
+} RenderBackend_Surface;
 
-typedef struct Backend_Glyph
+typedef struct RenderBackend_Glyph
 {
 	SDL_Surface *sdlsurface;
-} Backend_Glyph;
+} RenderBackend_Glyph;
 
-extern SDL_Window *window;
+SDL_Window *window;
 
 static SDL_Surface *window_sdlsurface;
 
-static Backend_Surface framebuffer;
+static RenderBackend_Surface framebuffer;
 
 static unsigned char glyph_colour_channels[3];
 static SDL_Surface *glyph_destination_sdlsurface;
@@ -43,7 +44,7 @@
 		sdl_rect->h = 0;
 }
 
-Backend_Surface* Backend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
+RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
 {
 	window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, 0);
 
@@ -58,7 +59,7 @@
 
 		if (framebuffer.sdlsurface != NULL)
 		{
-			PlatformBackend_PostWindowCreation();
+			Backend_PostWindowCreation();
 
 			return &framebuffer;
 		}
@@ -77,21 +78,21 @@
 	return NULL;
 }
 
-void Backend_Deinit(void)
+void RenderBackend_Deinit(void)
 {
 	SDL_FreeSurface(framebuffer.sdlsurface);
 	SDL_DestroyWindow(window);
 }
 
-void Backend_DrawScreen(void)
+void RenderBackend_DrawScreen(void)
 {
 	SDL_BlitSurface(framebuffer.sdlsurface, NULL, window_sdlsurface, NULL);
 	SDL_UpdateWindowSurface(window);
 }
 
-Backend_Surface* Backend_CreateSurface(unsigned int width, unsigned int height)
+RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height)
 {
-	Backend_Surface *surface = (Backend_Surface*)malloc(sizeof(Backend_Surface));
+	RenderBackend_Surface *surface = (RenderBackend_Surface*)malloc(sizeof(RenderBackend_Surface));
 
 	if (surface == NULL)
 		return NULL;
@@ -107,7 +108,7 @@
 	return surface;
 }
 
-void Backend_FreeSurface(Backend_Surface *surface)
+void RenderBackend_FreeSurface(RenderBackend_Surface *surface)
 {
 	if (surface == NULL)
 		return;
@@ -116,7 +117,7 @@
 	free(surface);
 }
 
-BOOL Backend_IsSurfaceLost(Backend_Surface *surface)
+BOOL RenderBackend_IsSurfaceLost(RenderBackend_Surface *surface)
 {
 	(void)surface;
 
@@ -123,13 +124,16 @@
 	return FALSE;
 }
 
-void Backend_RestoreSurface(Backend_Surface *surface)
+void RenderBackend_RestoreSurface(RenderBackend_Surface *surface)
 {
 	(void)surface;
 }
 
-unsigned char* Backend_LockSurface(Backend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
+unsigned char* RenderBackend_LockSurface(RenderBackend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
 {
+	(void)width;
+	(void)height;
+
 	if (surface == NULL)
 		return NULL;
 
@@ -137,12 +141,14 @@
 	return (unsigned char*)surface->sdlsurface->pixels;
 }
 
-void Backend_UnlockSurface(Backend_Surface *surface, unsigned int width, unsigned int height)
+void RenderBackend_UnlockSurface(RenderBackend_Surface *surface, unsigned int width, unsigned int height)
 {
 	(void)surface;
+	(void)width;
+	(void)height;
 }
 
-void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
+void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RECT *rect, RenderBackend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
 	if (source_surface == NULL || destination_surface == NULL)
 		return;
@@ -161,7 +167,7 @@
 	SDL_BlitSurface(source_surface->sdlsurface, &source_rect, destination_surface->sdlsurface, &destination_rect);
 }
 
-void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
+void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
 	if (surface == NULL)
 		return;
@@ -172,9 +178,9 @@
 	SDL_FillRect(surface->sdlsurface, &destination_rect, SDL_MapRGB(surface->sdlsurface->format, red, green, blue));
 }
 
-Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
+RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
 {
-	Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
+	RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)malloc(sizeof(RenderBackend_Glyph));
 
 	if (glyph == NULL)
 		return NULL;
@@ -204,7 +210,7 @@
 	return glyph;
 }
 
-void Backend_UnloadGlyph(Backend_Glyph *glyph)
+void RenderBackend_UnloadGlyph(RenderBackend_Glyph *glyph)
 {
 	if (glyph == NULL)
 		return;
@@ -213,7 +219,7 @@
 	free(glyph);
 }
 
-void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
+void RenderBackend_PrepareToDrawGlyphs(RenderBackend_Surface *destination_surface, const unsigned char *colour_channels)
 {
 	if (destination_surface == NULL)
 		return;
@@ -223,7 +229,7 @@
 	memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
 }
 
-void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
+void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y)
 {
 	if (glyph == NULL)
 		return;
@@ -239,17 +245,17 @@
 	SDL_BlitSurface(glyph->sdlsurface, NULL, glyph_destination_sdlsurface, &rect);
 }
 
-void Backend_FlushGlyphs(void)
+void RenderBackend_FlushGlyphs(void)
 {
 	
 }
 
-void Backend_HandleRenderTargetLoss(void)
+void RenderBackend_HandleRenderTargetLoss(void)
 {
 	// No problem for us
 }
 
-void Backend_HandleWindowResize(unsigned int width, unsigned int height)
+void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height)
 {
 	(void)width;
 	(void)height;
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -12,13 +12,14 @@
 
 #include "../../WindowsWrapper.h"
 
-#include "../Platform.h"
+#include "../Misc.h"
+#include "../SDL2/Window.h"
 #include "../../Draw.h"
 #include "../../Ending.h"
 #include "../../MapName.h"
 #include "../../TextScr.h"
 
-typedef struct Backend_Surface
+typedef struct RenderBackend_Surface
 {
 	SDL_Texture *texture;
 	unsigned char *pixels;
@@ -26,24 +27,24 @@
 	unsigned int height;
 	BOOL lost;
 
-	struct Backend_Surface *next;
-	struct Backend_Surface *prev;
-} Backend_Surface;
+	struct RenderBackend_Surface *next;
+	struct RenderBackend_Surface *prev;
+} RenderBackend_Surface;
 
-typedef struct Backend_Glyph
+typedef struct RenderBackend_Glyph
 {
 	unsigned char *pixels;
 	unsigned int width;
 	unsigned int height;
-} Backend_Glyph;
+} RenderBackend_Glyph;
 
-extern SDL_Window *window;
+SDL_Window *window;
 
 static SDL_Renderer *renderer;
 
-static Backend_Surface framebuffer;
+static RenderBackend_Surface framebuffer;
 
-static Backend_Surface *surface_list_head;
+static RenderBackend_Surface *surface_list_head;
 
 static unsigned char glyph_colour_channels[3];
 
@@ -77,7 +78,7 @@
 
 	for (int i = 0; i < count; ++i)
 	{
-		Backend_Glyph *glyph = (Backend_Glyph*)sprites[i].image_id;
+		RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)sprites[i].image_id;
 
 		SDL_Rect source_rect = {(int)(texture_w * sprites[i].minx), (int)(texture_h * sprites[i].maxy), (int)glyph->width, (int)glyph->height};
 		SDL_Rect destination_rect = {(int)sprites[i].x, (int)sprites[i].y, (int)glyph->width, (int)glyph->height};
@@ -91,7 +92,7 @@
 {
 	(void)udata;
 
-	Backend_Glyph *glyph = (Backend_Glyph*)image_id;
+	RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)image_id;
 
 	memcpy(buffer, glyph->pixels, bytes_to_fill);
 }
@@ -116,7 +117,7 @@
 	SDL_DestroyTexture((SDL_Texture*)texture_id);
 }
 
-Backend_Surface* Backend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
+RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
 {
 	puts("Available SDL2 render drivers:");
 
@@ -166,7 +167,7 @@
 				config.delete_texture_callback = GlyphBatch_DestroyTexture;
 				spritebatch_init(&glyph_batcher, &config, NULL);
 
-				PlatformBackend_PostWindowCreation();
+				Backend_PostWindowCreation();
 
 				return &framebuffer;
 			}
@@ -193,7 +194,7 @@
 	return NULL;
 }
 
-void Backend_Deinit(void)
+void RenderBackend_Deinit(void)
 {
 	spritebatch_term(&glyph_batcher);
 	SDL_DestroyTexture(framebuffer.texture);
@@ -201,7 +202,7 @@
 	SDL_DestroyWindow(window);
 }
 
-void Backend_DrawScreen(void)
+void RenderBackend_DrawScreen(void)
 {
 	spritebatch_tick(&glyph_batcher);
 
@@ -210,9 +211,9 @@
 	SDL_RenderPresent(renderer);
 }
 
-Backend_Surface* Backend_CreateSurface(unsigned int width, unsigned int height)
+RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height)
 {
-	Backend_Surface *surface = (Backend_Surface*)malloc(sizeof(Backend_Surface));
+	RenderBackend_Surface *surface = (RenderBackend_Surface*)malloc(sizeof(RenderBackend_Surface));
 
 	if (surface == NULL)
 		return NULL;
@@ -240,7 +241,7 @@
 	return surface;
 }
 
-void Backend_FreeSurface(Backend_Surface *surface)
+void RenderBackend_FreeSurface(RenderBackend_Surface *surface)
 {
 	if (surface == NULL)
 		return;
@@ -255,17 +256,17 @@
 	free(surface);
 }
 
-BOOL Backend_IsSurfaceLost(Backend_Surface *surface)
+BOOL RenderBackend_IsSurfaceLost(RenderBackend_Surface *surface)
 {
 	return surface->lost;
 }
 
-void Backend_RestoreSurface(Backend_Surface *surface)
+void RenderBackend_RestoreSurface(RenderBackend_Surface *surface)
 {
 	surface->lost = FALSE;
 }
 
-unsigned char* Backend_LockSurface(Backend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
+unsigned char* RenderBackend_LockSurface(RenderBackend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
 {
 	if (surface == NULL)
 		return NULL;
@@ -277,7 +278,7 @@
 	return surface->pixels;
 }
 
-void Backend_UnlockSurface(Backend_Surface *surface, unsigned int width, unsigned int height)
+void RenderBackend_UnlockSurface(RenderBackend_Surface *surface, unsigned int width, unsigned int height)
 {
 	if (surface == NULL)
 		return;
@@ -313,7 +314,7 @@
 	free(buffer);
 }
 
-void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
+void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RECT *rect, RenderBackend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
 	if (source_surface == NULL || destination_surface == NULL)
 		return;
@@ -329,7 +330,7 @@
 	SDL_RenderCopy(renderer, source_surface->texture, &source_rect, &destination_rect);
 }
 
-void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
+void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
 	if (surface == NULL)
 		return;
@@ -350,9 +351,9 @@
 	SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
 }
 
-Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
+RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
 {
-	Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
+	RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)malloc(sizeof(RenderBackend_Glyph));
 
 	if (glyph == NULL)
 		return NULL;
@@ -386,7 +387,7 @@
 	return glyph;
 }
 
-void Backend_UnloadGlyph(Backend_Glyph *glyph)
+void RenderBackend_UnloadGlyph(RenderBackend_Glyph *glyph)
 {
 	if (glyph == NULL)
 		return;
@@ -395,7 +396,7 @@
 	free(glyph);
 }
 
-void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
+void RenderBackend_PrepareToDrawGlyphs(RenderBackend_Surface *destination_surface, const unsigned char *colour_channels)
 {
 	if (destination_surface == NULL)
 		return;
@@ -405,24 +406,24 @@
 	memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
 }
 
-void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
+void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y)
 {
 	spritebatch_push(&glyph_batcher, (SPRITEBATCH_U64)glyph, glyph->width, glyph->height, x, y, 1.0f, 1.0f, 0.0f, 0.0f, 0);
 }
 
-void Backend_FlushGlyphs(void)
+void RenderBackend_FlushGlyphs(void)
 {
 	spritebatch_defrag(&glyph_batcher);
 	spritebatch_flush(&glyph_batcher);
 }
 
-void Backend_HandleRenderTargetLoss(void)
+void RenderBackend_HandleRenderTargetLoss(void)
 {
-	for (Backend_Surface *surface = surface_list_head; surface != NULL; surface = surface->next)
+	for (RenderBackend_Surface *surface = surface_list_head; surface != NULL; surface = surface->next)
 		surface->lost = TRUE;
 }
 
-void Backend_HandleWindowResize(unsigned int width, unsigned int height)
+void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height)
 {
 	(void)width;
 	(void)height;
--- a/src/Backends/Rendering/Software.cpp
+++ b/src/Backends/Rendering/Software.cpp
@@ -9,36 +9,37 @@
 #include "../../WindowsWrapper.h"
 #include "../../Attributes.h"
 
-#include "../Platform.h"
+#include "../Misc.h"
+#include "../SDL2/Window.h"
 
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 
-typedef struct Backend_Surface
+typedef struct RenderBackend_Surface
 {
 	unsigned char *pixels;
 	unsigned int width;
 	unsigned int height;
 	unsigned int pitch;
-} Backend_Surface;
+} RenderBackend_Surface;
 
-typedef struct Backend_Glyph
+typedef struct RenderBackend_Glyph
 {
 	unsigned char *pixels;
 	unsigned int width;
 	unsigned int height;
-} Backend_Glyph;
+} RenderBackend_Glyph;
 
-extern SDL_Window *window;
-
 static SDL_Surface *window_sdlsurface;
 static SDL_Surface *framebuffer_sdlsurface;
-static Backend_Surface framebuffer;
+static RenderBackend_Surface framebuffer;
 
 static unsigned char glyph_colour_channels[3];
-static Backend_Surface *glyph_destination_surface;
+static RenderBackend_Surface *glyph_destination_surface;
 
-Backend_Surface* Backend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
+SDL_Window *window;
+
+RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
 {
 	window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, 0);
 
@@ -58,13 +59,13 @@
 			framebuffer.height = framebuffer_sdlsurface->h;
 			framebuffer.pitch = framebuffer_sdlsurface->pitch;
 
-			PlatformBackend_PostWindowCreation();
+			Backend_PostWindowCreation();
 
 			return &framebuffer;
 		}
 		else
 		{
-			PlatformBackend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create framebuffer surface");
+			Backend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create framebuffer surface");
 		}
 
 		SDL_DestroyWindow(window);
@@ -71,27 +72,27 @@
 	}
 	else
 	{
-		PlatformBackend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create window");
+		Backend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create window");
 	}
 
 	return NULL;
 }
 
-void Backend_Deinit(void)
+void RenderBackend_Deinit(void)
 {
 	SDL_FreeSurface(framebuffer_sdlsurface);
 	SDL_DestroyWindow(window);
 }
 
-void Backend_DrawScreen(void)
+void RenderBackend_DrawScreen(void)
 {
 	SDL_BlitSurface(framebuffer_sdlsurface, NULL, window_sdlsurface, NULL);
 	SDL_UpdateWindowSurface(window);
 }
 
-Backend_Surface* Backend_CreateSurface(unsigned int width, unsigned int height)
+RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height)
 {
-	Backend_Surface *surface = (Backend_Surface*)malloc(sizeof(Backend_Surface));
+	RenderBackend_Surface *surface = (RenderBackend_Surface*)malloc(sizeof(RenderBackend_Surface));
 
 	if (surface == NULL)
 		return NULL;
@@ -111,7 +112,7 @@
 	return surface;
 }
 
-void Backend_FreeSurface(Backend_Surface *surface)
+void RenderBackend_FreeSurface(RenderBackend_Surface *surface)
 {
 	if (surface == NULL)
 		return;
@@ -120,7 +121,7 @@
 	free(surface);
 }
 
-BOOL Backend_IsSurfaceLost(Backend_Surface *surface)
+BOOL RenderBackend_IsSurfaceLost(RenderBackend_Surface *surface)
 {
 	(void)surface;
 
@@ -127,12 +128,12 @@
 	return FALSE;
 }
 
-void Backend_RestoreSurface(Backend_Surface *surface)
+void RenderBackend_RestoreSurface(RenderBackend_Surface *surface)
 {
 	(void)surface;
 }
 
-unsigned char* Backend_LockSurface(Backend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
+unsigned char* RenderBackend_LockSurface(RenderBackend_Surface *surface, unsigned int *pitch, unsigned int width, unsigned int height)
 {
 	(void)width;
 	(void)height;
@@ -144,7 +145,7 @@
 	return surface->pixels;
 }
 
-void Backend_UnlockSurface(Backend_Surface *surface, unsigned int width, unsigned int height)
+void RenderBackend_UnlockSurface(RenderBackend_Surface *surface, unsigned int width, unsigned int height)
 {
 	(void)surface;
 	(void)width;
@@ -151,7 +152,7 @@
 	(void)height;
 }
 
-ATTRIBUTE_HOT void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key)
+ATTRIBUTE_HOT void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RECT *rect, RenderBackend_Surface *destination_surface, long x, long y, BOOL colour_key)
 {
 	if (source_surface == NULL || destination_surface == NULL)
 		return;
@@ -234,7 +235,7 @@
 	}
 }
 
-ATTRIBUTE_HOT void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
+ATTRIBUTE_HOT void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
 {
 	if (surface == NULL)
 		return;
@@ -292,9 +293,9 @@
 	}
 }
 
-Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
+RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
 {
-	Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
+	RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)malloc(sizeof(RenderBackend_Glyph));
 
 	if (glyph == NULL)
 		return NULL;
@@ -307,8 +308,6 @@
 		return NULL;
 	}
 
-	unsigned char *destination_pointer = glyph->pixels;
-
 	for (unsigned int y = 0; y < height; ++y)
 		memcpy(&glyph->pixels[y * width], &pixels[y * pitch], width);
 
@@ -318,7 +317,7 @@
 	return glyph;
 }
 
-void Backend_UnloadGlyph(Backend_Glyph *glyph)
+void RenderBackend_UnloadGlyph(RenderBackend_Glyph *glyph)
 {
 	if (glyph == NULL)
 		return;
@@ -327,7 +326,7 @@
 	free(glyph);
 }
 
-void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
+void RenderBackend_PrepareToDrawGlyphs(RenderBackend_Surface *destination_surface, const unsigned char *colour_channels)
 {
 	if (destination_surface == NULL)
 		return;
@@ -337,7 +336,7 @@
 	memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
 }
 
-void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
+void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y)
 {
 	if (glyph == NULL)
 		return;
@@ -361,17 +360,17 @@
 	}
 }
 
-void Backend_FlushGlyphs(void)
+void RenderBackend_FlushGlyphs(void)
 {
 	
 }
 
-void Backend_HandleRenderTargetLoss(void)
+void RenderBackend_HandleRenderTargetLoss(void)
 {
 	// No problem for us
 }
 
-void Backend_HandleWindowResize(unsigned int width, unsigned int height)
+void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height)
 {
 	(void)width;
 	(void)height;
--- /dev/null
+++ b/src/Backends/SDL2/Controller.cpp
@@ -1,0 +1,101 @@
+#include "../Controller.h"
+#include "Controller.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "SDL.h"
+
+#include "../../WindowsWrapper.h"
+
+#define DEADZONE 10000;
+
+static SDL_Joystick *joystick;
+static int joystick_neutral_x;
+static int joystick_neutral_y;
+
+BOOL ControllerBackend_Init(void)
+{
+	SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+
+	return TRUE;
+}
+
+void ControllerBackend_Deinit(void)
+{
+	if (joystick != NULL)
+	{
+		SDL_JoystickClose(joystick);
+		joystick = NULL;
+	}
+
+	SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+}
+
+BOOL ControllerBackend_GetJoystickStatus(JOYSTICK_STATUS *status)
+{
+	if (joystick == NULL)
+		return FALSE;
+
+	// Read axis
+	const Sint16 joystick_x = SDL_JoystickGetAxis(joystick, 0);
+	const Sint16 joystick_y = SDL_JoystickGetAxis(joystick, 1);
+
+	status->bLeft = joystick_x < joystick_neutral_x - DEADZONE;
+	status->bRight = joystick_x > joystick_neutral_x + DEADZONE;
+	status->bUp = joystick_y < joystick_neutral_y - DEADZONE;
+	status->bDown = joystick_y > joystick_neutral_y + DEADZONE;
+
+	// The original `Input.cpp` assumed there were 32 buttons (because of DirectInput's `DIJOYSTATE` struct)
+	int numButtons = SDL_JoystickNumButtons(joystick);
+	if (numButtons > 32)
+		numButtons = 32;
+
+	// Read whatever buttons actually exist
+	for (int i = 0; i < numButtons; ++i)
+		status->bButton[i] = SDL_JoystickGetButton(joystick, i);
+
+	// Blank the buttons that do not
+	for (int i = numButtons; i < 32; ++i)
+		status->bButton[i] = FALSE;
+
+	return TRUE;
+}
+
+BOOL ControllerBackend_ResetJoystickStatus(void)
+{
+	if (joystick == NULL)
+		return FALSE;
+
+	// The code that would normally run here has been moved to JoystickCallback, to better-support hotplugging
+
+	return TRUE;
+}
+
+void ControllerBackend_JoystickConnect(Sint32 joystick_id)
+{
+	printf("Joystick #%d connected - %s\n", joystick_id, SDL_JoystickNameForIndex(joystick_id));
+
+	if (joystick == NULL)
+	{
+		joystick = SDL_JoystickOpen(joystick_id);
+
+		if (joystick != NULL)
+		{
+			printf("Joystick #%d selected\n", joystick_id);
+
+			// Reset default stick positions (this is performed in ResetJoystickStatus in vanilla Cave Story
+			joystick_neutral_x = SDL_JoystickGetAxis(joystick, 0);
+			joystick_neutral_y = SDL_JoystickGetAxis(joystick, 1);
+		}
+	}
+}
+
+void ControllerBackend_JoystickDisconnect(Sint32 joystick_id)
+{
+	if (joystick_id == SDL_JoystickInstanceID(joystick))
+	{
+		printf("Joystick #%d disconnected\n", joystick_id);
+		joystick = NULL;
+	}
+}
--- /dev/null
+++ b/src/Backends/SDL2/Controller.h
@@ -1,0 +1,8 @@
+#pragma once
+
+#include "SDL.h"
+
+#include "../../WindowsWrapper.h"
+
+void ControllerBackend_JoystickConnect(Sint32 joystick_id);
+void ControllerBackend_JoystickDisconnect(Sint32 joystick_id);
--- /dev/null
+++ b/src/Backends/SDL2/Misc.cpp
@@ -1,0 +1,256 @@
+#include "../Misc.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "SDL.h"
+
+#include "../../WindowsWrapper.h"
+
+#include "Controller.h"
+#include "Window.h"
+#include "../Rendering.h"
+#include "../../Main.h"
+#include "../../Organya.h"
+#include "../../Profile.h"
+#include "../../Resource.h"
+
+#define DO_KEY(SDL_KEY, BACKEND_KEY) \
+	case SDL_KEY: \
+		backend_keyboard_state[BACKEND_KEY] = event.key.type == SDL_KEYDOWN; \
+		break;
+
+BOOL bActive = TRUE;
+BOOL backend_keyboard_state[BACKEND_KEYBOARD_TOTAL];
+BOOL backend_previous_keyboard_state[BACKEND_KEYBOARD_TOTAL];
+
+static SDL_Surface *cursor_surface;
+static SDL_Cursor *cursor;
+
+void Backend_Init(void)
+{
+	SDL_Init(SDL_INIT_EVENTS);
+
+	SDL_InitSubSystem(SDL_INIT_VIDEO);
+
+	puts("Available SDL2 video drivers:");
+
+	for (int i = 0; i < SDL_GetNumVideoDrivers(); ++i)
+		puts(SDL_GetVideoDriver(i));
+
+	printf("Selected SDL2 video driver: %s\n", SDL_GetCurrentVideoDriver());
+}
+
+void Backend_Deinit(void)
+{
+	if (cursor != NULL)
+		SDL_FreeCursor(cursor);
+
+	if (cursor_surface != NULL)
+		SDL_FreeSurface(cursor_surface);
+
+	SDL_Quit();
+}
+
+void Backend_PostWindowCreation(void)
+{
+	
+}
+
+BOOL Backend_GetBasePath(char *string_buffer)
+{
+	char *base_path = SDL_GetBasePath();
+	// Trim the trailing '/'
+	size_t base_path_length = strlen(base_path);
+	base_path[base_path_length - 1] = '\0';
+	strcpy(string_buffer, base_path);
+	SDL_free(base_path);
+
+	return TRUE;
+}
+
+void Backend_HideMouse(void)
+{
+	SDL_ShowCursor(SDL_DISABLE);
+}
+
+void Backend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
+{
+	SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormatFrom((void*)rgb_pixels, width, height, 0, width * 3, SDL_PIXELFORMAT_RGB24);
+	SDL_SetWindowIcon(window, surface);
+	SDL_FreeSurface(surface);
+}
+
+void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
+{
+	cursor_surface = SDL_CreateRGBSurfaceWithFormatFrom((void*)rgb_pixels, width, height, 0, width * 3, SDL_PIXELFORMAT_RGB24);
+	SDL_SetColorKey(cursor_surface, SDL_TRUE, SDL_MapRGB(cursor_surface->format, 0xFF, 0, 0xFF));
+	cursor = SDL_CreateColorCursor(cursor_surface, 0, 0);
+	SDL_SetCursor(cursor);
+}
+
+void PlaybackBackend_EnableDragAndDrop(void)
+{
+	SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
+}
+
+BOOL Backend_SystemTask(void)
+{
+	memcpy(backend_previous_keyboard_state, backend_keyboard_state, sizeof(backend_keyboard_state));
+
+	while (SDL_PollEvent(NULL) || !bActive)
+	{
+		SDL_Event event;
+
+		if (!SDL_WaitEvent(&event))
+			return FALSE;
+
+		switch (event.type)
+		{
+			case SDL_KEYUP:
+			case SDL_KEYDOWN:
+				switch (event.key.keysym.sym)
+				{
+					DO_KEY(SDLK_a, BACKEND_KEYBOARD_A)
+					DO_KEY(SDLK_b, BACKEND_KEYBOARD_B)
+					DO_KEY(SDLK_c, BACKEND_KEYBOARD_C)
+					DO_KEY(SDLK_d, BACKEND_KEYBOARD_D)
+					DO_KEY(SDLK_e, BACKEND_KEYBOARD_E)
+					DO_KEY(SDLK_f, BACKEND_KEYBOARD_F)
+					DO_KEY(SDLK_g, BACKEND_KEYBOARD_G)
+					DO_KEY(SDLK_h, BACKEND_KEYBOARD_H)
+					DO_KEY(SDLK_i, BACKEND_KEYBOARD_I)
+					DO_KEY(SDLK_j, BACKEND_KEYBOARD_J)
+					DO_KEY(SDLK_k, BACKEND_KEYBOARD_K)
+					DO_KEY(SDLK_l, BACKEND_KEYBOARD_L)
+					DO_KEY(SDLK_m, BACKEND_KEYBOARD_M)
+					DO_KEY(SDLK_n, BACKEND_KEYBOARD_N)
+					DO_KEY(SDLK_o, BACKEND_KEYBOARD_O)
+					DO_KEY(SDLK_p, BACKEND_KEYBOARD_P)
+					DO_KEY(SDLK_q, BACKEND_KEYBOARD_Q)
+					DO_KEY(SDLK_r, BACKEND_KEYBOARD_R)
+					DO_KEY(SDLK_s, BACKEND_KEYBOARD_S)
+					DO_KEY(SDLK_t, BACKEND_KEYBOARD_T)
+					DO_KEY(SDLK_u, BACKEND_KEYBOARD_U)
+					DO_KEY(SDLK_v, BACKEND_KEYBOARD_V)
+					DO_KEY(SDLK_w, BACKEND_KEYBOARD_W)
+					DO_KEY(SDLK_x, BACKEND_KEYBOARD_X)
+					DO_KEY(SDLK_y, BACKEND_KEYBOARD_Y)
+					DO_KEY(SDLK_z, BACKEND_KEYBOARD_Z)
+					DO_KEY(SDLK_0, BACKEND_KEYBOARD_0)
+					DO_KEY(SDLK_1, BACKEND_KEYBOARD_1)
+					DO_KEY(SDLK_2, BACKEND_KEYBOARD_2)
+					DO_KEY(SDLK_3, BACKEND_KEYBOARD_3)
+					DO_KEY(SDLK_4, BACKEND_KEYBOARD_4)
+					DO_KEY(SDLK_5, BACKEND_KEYBOARD_5)
+					DO_KEY(SDLK_6, BACKEND_KEYBOARD_6)
+					DO_KEY(SDLK_7, BACKEND_KEYBOARD_7)
+					DO_KEY(SDLK_8, BACKEND_KEYBOARD_8)
+					DO_KEY(SDLK_9, BACKEND_KEYBOARD_9)
+					DO_KEY(SDLK_F1, BACKEND_KEYBOARD_F1)
+					DO_KEY(SDLK_F2, BACKEND_KEYBOARD_F2)
+					DO_KEY(SDLK_F3, BACKEND_KEYBOARD_F3)
+					DO_KEY(SDLK_F4, BACKEND_KEYBOARD_F4)
+					DO_KEY(SDLK_F5, BACKEND_KEYBOARD_F5)
+					DO_KEY(SDLK_F6, BACKEND_KEYBOARD_F6)
+					DO_KEY(SDLK_F7, BACKEND_KEYBOARD_F7)
+					DO_KEY(SDLK_F8, BACKEND_KEYBOARD_F8)
+					DO_KEY(SDLK_F9, BACKEND_KEYBOARD_F9)
+					DO_KEY(SDLK_F10, BACKEND_KEYBOARD_F10)
+					DO_KEY(SDLK_F11, BACKEND_KEYBOARD_F11)
+					DO_KEY(SDLK_F12, BACKEND_KEYBOARD_F12)
+					DO_KEY(SDLK_UP, BACKEND_KEYBOARD_UP)
+					DO_KEY(SDLK_DOWN, BACKEND_KEYBOARD_DOWN)
+					DO_KEY(SDLK_LEFT, BACKEND_KEYBOARD_LEFT)
+					DO_KEY(SDLK_RIGHT, BACKEND_KEYBOARD_RIGHT)
+					DO_KEY(SDLK_ESCAPE, BACKEND_KEYBOARD_ESCAPE)
+					DO_KEY(SDLK_BACKQUOTE, BACKEND_KEYBOARD_BACK_QUOTE)
+					DO_KEY(SDLK_TAB, BACKEND_KEYBOARD_TAB)
+					DO_KEY(SDLK_CAPSLOCK, BACKEND_KEYBOARD_CAPS_LOCK)
+					DO_KEY(SDLK_LSHIFT, BACKEND_KEYBOARD_LEFT_SHIFT)
+					DO_KEY(SDLK_LCTRL, BACKEND_KEYBOARD_LEFT_CTRL)
+					DO_KEY(SDLK_LALT, BACKEND_KEYBOARD_LEFT_ALT)
+					DO_KEY(SDLK_SPACE, BACKEND_KEYBOARD_SPACE)
+					DO_KEY(SDLK_RALT, BACKEND_KEYBOARD_RIGHT_ALT)
+					DO_KEY(SDLK_RCTRL, BACKEND_KEYBOARD_RIGHT_CTRL)
+					DO_KEY(SDLK_RSHIFT, BACKEND_KEYBOARD_RIGHT_SHIFT)
+					DO_KEY(SDLK_RETURN, BACKEND_KEYBOARD_ENTER)
+					DO_KEY(SDLK_BACKSPACE, BACKEND_KEYBOARD_BACKSPACE)
+					DO_KEY(SDLK_MINUS, BACKEND_KEYBOARD_MINUS)
+					DO_KEY(SDLK_EQUALS, BACKEND_KEYBOARD_EQUALS)
+					DO_KEY(SDLK_LEFTBRACKET, BACKEND_KEYBOARD_LEFT_BRACKET)
+					DO_KEY(SDLK_RIGHTBRACKET, BACKEND_KEYBOARD_RIGHT_BRACKET)
+					DO_KEY(SDLK_BACKSLASH, BACKEND_KEYBOARD_BACK_SLASH)
+					DO_KEY(SDLK_SEMICOLON, BACKEND_KEYBOARD_SEMICOLON)
+					DO_KEY(SDLK_QUOTE, BACKEND_KEYBOARD_APOSTROPHE)
+					DO_KEY(SDLK_COMMA, BACKEND_KEYBOARD_COMMA)
+					DO_KEY(SDLK_PERIOD, BACKEND_KEYBOARD_PERIOD)
+					DO_KEY(SDLK_SLASH, BACKEND_KEYBOARD_FORWARD_SLASH)
+
+					default:
+						break;
+				}
+
+				break;
+
+			case SDL_JOYDEVICEADDED:
+				ControllerBackend_JoystickConnect(event.jdevice.which);
+				break;
+
+			case SDL_JOYDEVICEREMOVED:
+				ControllerBackend_JoystickDisconnect(event.jdevice.which);
+				break;
+
+			case SDL_DROPFILE:
+				LoadProfile(event.drop.file);
+				SDL_free(event.drop.file);
+				break;
+
+			case SDL_WINDOWEVENT:
+				switch (event.window.event)
+				{
+					case SDL_WINDOWEVENT_FOCUS_LOST:
+						InactiveWindow();
+						break;
+
+					case SDL_WINDOWEVENT_FOCUS_GAINED:
+						ActiveWindow();
+						break;
+
+					case SDL_WINDOWEVENT_RESIZED:
+					case SDL_WINDOWEVENT_SIZE_CHANGED:
+						RenderBackend_HandleWindowResize(event.window.data1, event.window.data2);
+						break;
+				}
+
+				break;
+
+			case SDL_QUIT:
+				StopOrganyaMusic();
+				return FALSE;
+
+			case SDL_RENDER_TARGETS_RESET:
+				RenderBackend_HandleRenderTargetLoss();
+				break;
+
+		}
+	}
+
+	return TRUE;
+}
+
+void Backend_ShowMessageBox(const char *title, const char *message)
+{
+	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, window);
+}
+
+unsigned long Backend_GetTicks(void)
+{
+	return SDL_GetTicks();
+}
+
+void Backend_Delay(unsigned int ticks)
+{
+	SDL_Delay(ticks);
+}
--- /dev/null
+++ b/src/Backends/SDL2/Window-OpenGL3.cpp
@@ -1,0 +1,100 @@
+#include "../Window-OpenGL.h"
+#include "Window.h"
+
+#include <stddef.h>
+
+#ifdef USE_OPENGLES2
+#include <GLES2/gl2.h>
+#else
+#include <glad/glad.h>
+#endif
+#include "SDL.h"
+
+#include "../../WindowsWrapper.h"
+
+#include "../Misc.h"
+#include "../../Resource.h"
+
+SDL_Window *window;
+
+static SDL_GLContext context;
+
+BOOL WindowBackend_OpenGL_CreateWindow(const char *window_title, int *screen_width, int *screen_height, BOOL fullscreen)
+{
+#ifdef USE_OPENGLES2
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#else
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+#endif
+
+	window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, *screen_width, *screen_height, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | (fullscreen ? SDL_WINDOW_FULLSCREEN : 0));
+
+	if (window != NULL)
+	{
+		context = SDL_GL_CreateContext(window);
+
+		if (context != NULL)
+		{
+			if (SDL_GL_MakeCurrent(window, context) == 0)
+			{
+			#ifndef USE_OPENGLES2
+				if (gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
+				{
+					// Check if the platform supports OpenGL 3.2
+					if (GLAD_GL_VERSION_3_2)
+					{
+			#endif
+						Backend_PostWindowCreation();
+
+						return TRUE;
+			#ifndef USE_OPENGLES2
+					}
+					else
+					{
+						Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Your system does not support OpenGL 3.2");
+					}
+				}
+				else
+				{
+					Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not load OpenGL functions");
+				}
+			#endif
+			}
+			else
+			{
+				Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "SDL_GL_MakeCurrent failed");
+			}
+
+			SDL_GL_DeleteContext(context);
+		}
+		else
+		{
+			Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not create OpenGL context");
+		}
+
+		SDL_DestroyWindow(window);
+	}
+	else
+	{
+		Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not create window");
+	}
+
+	return FALSE;
+}
+
+void WindowBackend_OpenGL_DestroyWindow(void)
+{
+	SDL_GL_DeleteContext(context);
+	SDL_DestroyWindow(window);
+}
+
+void WindowBackend_OpenGL_Display(void)
+{
+	SDL_GL_SwapWindow(window);
+}
--- /dev/null
+++ b/src/Backends/SDL2/Window-OpenGLES2.cpp
@@ -1,0 +1,2 @@
+#define USE_OPENGLES2
+#include "Window-OpenGL3.cpp"
--- /dev/null
+++ b/src/Backends/SDL2/Window.h
@@ -1,0 +1,5 @@
+#pragma once
+
+#include "SDL.h"
+
+extern SDL_Window *window;
--- /dev/null
+++ b/src/Backends/Window-OpenGL.h
@@ -1,0 +1,7 @@
+#pragma once
+
+#include "../WindowsWrapper.h"
+
+BOOL WindowBackend_OpenGL_CreateWindow(const char *window_title, int *screen_width, int *screen_height, BOOL fullscreen);
+void WindowBackend_OpenGL_DestroyWindow(void);
+void WindowBackend_OpenGL_Display(void);
--- a/src/Backends/Window.h
+++ /dev/null
@@ -1,7 +1,0 @@
-#pragma once
-
-#include "../WindowsWrapper.h"
-
-BOOL WindowBackend_OpenGL_CreateWindow(const char *window_title, int *screen_width, int *screen_height, BOOL fullscreen);
-void WindowBackend_OpenGL_DestroyWindow(void);
-void WindowBackend_OpenGL_Display(void);
--- a/src/Backends/Window/GLFW3-OpenGL3.cpp
+++ /dev/null
@@ -1,96 +1,0 @@
-#include "../Window.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#ifdef USE_OPENGLES2
-#include <GLES2/gl2.h>
-#else
-#include "../../../external/glad/include/glad/glad.h"
-#endif
-#include <GLFW/glfw3.h>
-
-#include "../../WindowsWrapper.h"
-
-#include "../Platform.h"
-
-// Horrible hack
-extern GLFWwindow *window;
-
-BOOL WindowBackend_OpenGL_CreateWindow(const char *window_title, int *screen_width, int *screen_height, BOOL fullscreen)
-{
-#ifdef USE_OPENGLES2
-	glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-#else
-	glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
-	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
-#endif
-
-	GLFWmonitor *monitor = NULL;
-
-	if (fullscreen)
-	{
-		monitor = glfwGetPrimaryMonitor();
-
-		if (monitor != NULL)
-		{
-			const GLFWvidmode *mode = glfwGetVideoMode(monitor);
-
-			*screen_width = mode->width;
-			*screen_height = mode->height;
-		}
-	}
-
-	window = glfwCreateWindow(*screen_width, *screen_height, window_title, monitor, NULL);
-
-	if (window != NULL)
-	{
-		glfwMakeContextCurrent(window);
-
-			#ifndef USE_OPENGLES2
-				if (gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
-				{
-					// Check if the platform supports OpenGL 3.2
-					if (GLAD_GL_VERSION_3_2)
-					{
-			#endif
-						PlatformBackend_PostWindowCreation();
-
-						return TRUE;
-			#ifndef USE_OPENGLES2
-					}
-					else
-					{
-						PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Your system does not support OpenGL 3.2");
-					}
-				}
-				else
-				{
-					PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not load OpenGL functions");
-				}
-			#endif
-
-		glfwDestroyWindow(window);
-	}
-	else
-	{
-		PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not create window");
-	}
-
-	return FALSE;
-}
-
-void WindowBackend_OpenGL_DestroyWindow(void)
-{
-	glfwDestroyWindow(window);
-}
-
-void WindowBackend_OpenGL_Display(void)
-{
-	glfwSwapBuffers(window);
-}
--- a/src/Backends/Window/GLFW3-OpenGLES2.cpp
+++ /dev/null
@@ -1,2 +1,0 @@
-#define USE_OPENGLES2
-#include "GLFW3-OpenGL3.cpp"
--- a/src/Backends/Window/SDL2-OpenGL3.cpp
+++ /dev/null
@@ -1,99 +1,0 @@
-#include "../Window.h"
-
-#include <stddef.h>
-
-#ifdef USE_OPENGLES2
-#include <GLES2/gl2.h>
-#else
-#include "../../../external/glad/include/glad/glad.h"
-#endif
-#include "SDL.h"
-
-#include "../../WindowsWrapper.h"
-
-#include "../Platform.h"
-#include "../../Resource.h"
-
-extern SDL_Window *window;
-
-static SDL_GLContext context;
-
-BOOL WindowBackend_OpenGL_CreateWindow(const char *window_title, int *screen_width, int *screen_height, BOOL fullscreen)
-{
-#ifdef USE_OPENGLES2
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
-#else
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
-#endif
-
-	window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, *screen_width, *screen_height, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | (fullscreen ? SDL_WINDOW_FULLSCREEN : 0));
-
-	if (window != NULL)
-	{
-		context = SDL_GL_CreateContext(window);
-
-		if (context != NULL)
-		{
-			if (SDL_GL_MakeCurrent(window, context) == 0)
-			{
-			#ifndef USE_OPENGLES2
-				if (gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
-				{
-					// Check if the platform supports OpenGL 3.2
-					if (GLAD_GL_VERSION_3_2)
-					{
-			#endif
-						PlatformBackend_PostWindowCreation();
-
-						return TRUE;
-			#ifndef USE_OPENGLES2
-					}
-					else
-					{
-						PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Your system does not support OpenGL 3.2");
-					}
-				}
-				else
-				{
-					PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not load OpenGL functions");
-				}
-			#endif
-			}
-			else
-			{
-				PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "SDL_GL_MakeCurrent failed");
-			}
-
-			SDL_GL_DeleteContext(context);
-		}
-		else
-		{
-			PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not create OpenGL context");
-		}
-
-		SDL_DestroyWindow(window);
-	}
-	else
-	{
-		PlatformBackend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not create window");
-	}
-
-	return FALSE;
-}
-
-void WindowBackend_OpenGL_DestroyWindow(void)
-{
-	SDL_GL_DeleteContext(context);
-	SDL_DestroyWindow(window);
-}
-
-void WindowBackend_OpenGL_Display(void)
-{
-	SDL_GL_SwapWindow(window);
-}
--- a/src/Backends/Window/SDL2-OpenGLES2.cpp
+++ /dev/null
@@ -1,2 +1,0 @@
-#define USE_OPENGLES2
-#include "SDL2-OpenGL3.cpp"
--- a/src/BossAlmo1.cpp
+++ b/src/BossAlmo1.cpp
@@ -1,5 +1,7 @@
 #include "BossAlmo1.h"
 
+#include <stddef.h>
+
 #include "WindowsWrapper.h"
 
 #include "Boss.h"
--- a/src/BossAlmo2.cpp
+++ b/src/BossAlmo2.cpp
@@ -1,5 +1,7 @@
 #include "BossAlmo2.h"
 
+#include <stddef.h>
+
 #include "WindowsWrapper.h"
 
 #include "Boss.h"
@@ -610,7 +612,7 @@
 			for (i = 0; i < 100; ++i)
 				SetNpChar(4, npc->x + (Random(-128, 128) * 0x200), npc->y + (Random(-64, 64) * 0x200), Random(-128, 128) * 0x200, Random(-128, 128) * 0x200, 0, NULL, 0);
 
-			DeleteNpCharCode(282, 1);
+			DeleteNpCharCode(282, TRUE);
 			gBoss[11].bits &= ~NPC_SHOOTABLE;
 
 			for (i = 0; i < 12; ++i)
@@ -663,8 +665,8 @@
 				for (i = 0; i < 20; ++i)
 					gBoss[i].cond = 0;
 
-				DeleteNpCharCode(158, 1);
-				DeleteNpCharCode(301, 1);
+				DeleteNpCharCode(158, TRUE);
+				DeleteNpCharCode(301, TRUE);
 			}
 
 			break;
--- a/src/BossBallos.cpp
+++ b/src/BossBallos.cpp
@@ -1,5 +1,7 @@
 #include "BossBallos.h"
 
+#include <stddef.h>
+
 #include "WindowsWrapper.h"
 
 #include "Boss.h"
@@ -469,7 +471,7 @@
 			npc->act_wait = 0;
 			npc->xm = 0;
 			npc->ym = 0;
-			DeleteNpCharCode(339, 0);
+			DeleteNpCharCode(339, FALSE);
 			// Fallthrough
 		case 401:
 			npc->y += ((159 * 0x200) - npc->y) / 8;
@@ -674,8 +676,8 @@
 				gBoss[4].cond = 0;
 				gBoss[5].cond = 0;
 
-				DeleteNpCharCode(350, 1);
-				DeleteNpCharCode(348, 1);
+				DeleteNpCharCode(350, TRUE);
+				DeleteNpCharCode(348, TRUE);
 			}
 
 			break;
--- a/src/BossIronH.cpp
+++ b/src/BossIronH.cpp
@@ -167,9 +167,9 @@
 			for (i = 0; i < 0x20; ++i)
 				SetNpChar(4, npc->x + (Random(-128, 128) * 0x200), npc->y + (Random(-64, 64) * 0x200), Random(-128, 128) * 0x200, Random(-128, 128) * 0x200, 0, NULL, 0x100);
 
-			DeleteNpCharCode(197, 1);
-			DeleteNpCharCode(271, 1);
-			DeleteNpCharCode(272, 1);
+			DeleteNpCharCode(197, TRUE);
+			DeleteNpCharCode(271, TRUE);
+			DeleteNpCharCode(272, TRUE);
 			// Fallthrough
 		case 1001:
 			npc->tgt_x -= 1 * 0x200;
--- a/src/BossOhm.cpp
+++ b/src/BossOhm.cpp
@@ -1,6 +1,6 @@
 #include "BossOhm.h"
 
-#include <string.h>
+#include <stddef.h>
 
 #include "WindowsWrapper.h"
 
@@ -381,7 +381,7 @@
 				gBoss[0].count1 = 0;
 			}
 
-			if (gBoss[0].act_wait < 30 && !(gBoss[0].act_wait % 5))
+			if (gBoss[0].act_wait < 30 && gBoss[0].act_wait % 5 == 0)
 			{
 				SetNpChar(48, gBoss[0].x, gBoss[0].y - (16 * 0x200), Random(-341, 341), -0x333, 0, NULL, 0x100);
 				PlaySoundObject(39, 1);
@@ -518,6 +518,6 @@
 		gBoss[0].act_wait = 0;
 		gBoss[0].damage = 0;
 		gBoss[5].damage = 0;
-		DeleteNpCharCode(48, 1);
+		DeleteNpCharCode(48, TRUE);
 	}
 }
--- a/src/BossPress.cpp
+++ b/src/BossPress.cpp
@@ -152,8 +152,8 @@
 			npc->act_wait = 0;
 			npc->count1 = 0;
 
-			DeleteNpCharCode(325, 1);
-			DeleteNpCharCode(330, 1);
+			DeleteNpCharCode(325, TRUE);
+			DeleteNpCharCode(330, TRUE);
 			// Fallthrough
 		case 501:
 			if (++npc->act_wait % 0x10 == 0)
--- a/src/BossTwinD.cpp
+++ b/src/BossTwinD.cpp
@@ -524,7 +524,7 @@
 		case 1020:
 			if (++gBoss[0].act_wait > 50)
 			{
-				DeleteNpCharCode(211, 1);
+				DeleteNpCharCode(211, TRUE);
 				gBoss[0].cond = 0;
 				gBoss[1].cond = 0;
 				gBoss[2].cond = 0;
--- a/src/BossX.cpp
+++ b/src/BossX.cpp
@@ -1,5 +1,7 @@
 #include "BossX.h"
 
+#include <stddef.h>
+
 #include "WindowsWrapper.h"
 
 #include "Boss.h"
@@ -259,7 +261,7 @@
 					break;
 			}
 
-			SetNpChar(158, npc->x + x, npc->y + y, 0, 0, direct, 0, 0x100);
+			SetNpChar(158, npc->x + x, npc->y + y, 0, 0, direct, NULL, 0x100);
 			PlaySoundObject(39, 1);
 			npc->act_wait = 120;
 
@@ -858,7 +860,7 @@
 				for (i = 0; i < 20; ++i)
 					gBoss[i].cond = 0;
 
-				DeleteNpCharCode(158, 1);
+				DeleteNpCharCode(158, TRUE);
 				SetNpChar(159, npc->x, npc->y - (24 * 0x200), 0, 0, 0, NULL, 0);
 			}
 
--- a/src/Bullet.cpp
+++ b/src/Bullet.cpp
@@ -100,53 +100,72 @@
 	}
 }
 
-BULLET_TABLE gBulTbl[46] =
-{
+BULLET_TABLE gBulTbl[46] = {
+	// Null
 	{0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}},
+	// Snake
 	{4, 1, 20, 36, 4, 4, 2, 2, {8, 8, 8, 8}},
 	{6, 1, 23, 36, 4, 4, 2, 2, {8, 8, 8, 8}},
 	{8, 1, 30, 36, 4, 4, 2, 2, {8, 8, 8, 8}},
+	// Polar Star
 	{1, 1, 8, 32, 6, 6, 2, 2, {8, 8, 8, 8}},
 	{2, 1, 12, 32, 6, 6, 2, 2, {8, 8, 8, 8}},
 	{4, 1, 16, 32, 6, 6, 2, 2, {8, 8, 8, 8}},
+	// Fireball
 	{2, 2, 100, 8, 8, 16, 4, 2, {8, 8, 8, 8}},
 	{3, 2, 100, 8, 4, 4, 4, 2, {8, 8, 8, 8}},
 	{3, 2, 100, 8, 4, 4, 4, 2, {8, 8, 8, 8}},
+	// Machine Gun
 	{2, 1, 20, 32, 2, 2, 2, 2, {8, 8, 8, 8}},
 	{4, 1, 20, 32, 2, 2, 2, 2, {8, 8, 8, 8}},
 	{6, 1, 20, 32, 2, 2, 2, 2, {8, 8, 8, 8}},
+	// Missile Launcher
 	{0, 10, 50, 40, 2, 2, 2, 2, {8, 8, 8, 8}},
 	{0, 10, 70, 40, 4, 4, 4, 4, {8, 8, 8, 8}},
 	{0, 10, 90, 40, 4, 4, 0, 0, {8, 8, 8, 8}},
+	// Missile Launcher explosion
 	{1, 100, 100, 20, 16, 16, 0, 0, {0, 0, 0, 0}},
 	{1, 100, 100, 20, 16, 16, 0, 0, {0, 0, 0, 0}},
 	{1, 100, 100, 20, 16, 16, 0, 0, {0, 0, 0, 0}},
+	// Bubbler
 	{1, 1, 20, 8, 2, 2, 2, 2, {4, 4, 4, 4}},
 	{2, 1, 20, 8, 2, 2, 2, 2, {4, 4, 4, 4}},
 	{2, 1, 20, 8, 4, 4, 4, 4, {4, 4, 4, 4}},
+	// Bubbler level 3 thorns
 	{3, 1, 32, 32, 2, 2, 2, 2, {4, 4, 4, 4}},
+	// Blade slashes
 	{0, 100, 0, 36, 8, 8, 8, 8, {12, 12, 12, 12}},
+	// Falling spike that deals 127 damage
 	{127, 1, 2, 4, 8, 4, 8, 4, {0, 0, 0, 0}},
+	// Blade
 	{15, 1, 30, 36, 8, 8, 4, 2, {8, 8, 8, 8}},
 	{6, 3, 18, 36, 10, 10, 4, 2, {12, 12, 12, 12}},
 	{1, 100, 30, 36, 6, 6, 4, 4, {12, 12, 12, 12}},
+	// Super Missile Launcher
 	{0, 10, 30, 40, 2, 2, 2, 2, {8, 8, 8, 8}},
 	{0, 10, 40, 40, 4, 4, 4, 4, {8, 8, 8, 8}},
 	{0, 10, 40, 40, 4, 4, 0, 0, {8, 8, 8, 8}},
+	// Super Missile Launcher explosion
 	{2, 100, 100, 20, 12, 12, 0, 0, {0, 0, 0, 0}},
 	{2, 100, 100, 20, 12, 12, 0, 0, {0, 0, 0, 0}},
 	{2, 100, 100, 20, 12, 12, 0, 0, {0, 0, 0, 0}},
+	// Nemesis
 	{4, 4, 20, 32, 4, 4, 3, 3, {8, 8, 24, 8}},
 	{4, 2, 20, 32, 2, 2, 2, 2, {8, 8, 24, 8}},
 	{1, 1, 20, 32, 2, 2, 2, 2, {8, 8, 24, 8}},
+	// Spur
 	{4, 4, 30, 64, 6, 6, 3, 3, {8, 8, 8, 8}},
 	{8, 8, 30, 64, 6, 6, 3, 3, {8, 8, 8, 8}},
 	{12, 12, 30, 64, 6, 6, 3, 3, {8, 8, 8, 8}},
+	// Spur trail
 	{3, 100, 30, 32, 6, 6, 3, 3, {4, 4, 4, 4}},
 	{6, 100, 30, 32, 6, 6, 3, 3, {4, 4, 4, 4}},
 	{11, 100, 30, 32, 6, 6, 3, 3, {4, 4, 4, 4}},
+	// Curly's Nemesis
 	{4, 4, 20, 32, 4, 4, 3, 3, {8, 8, 24, 8}},
+	// Screen-nuke that kills all enemies
 	{0, 4, 4, 4, 0, 0, 0, 0, {0, 0, 0, 0}},
+	// Whimsical Star
 	{1, 1, 1, 36, 1, 1, 1, 1, {1, 1, 1, 1}}
 };
 
@@ -2258,6 +2277,7 @@
 
 			switch (gBul[i].code_bullet)
 			{
+				// Snake
 				case 1:
 					ActBullet_Frontia1(&gBul[i]);
 					break;
@@ -2267,6 +2287,8 @@
 				case 3:
 					ActBullet_Frontia2(&gBul[i], 3);
 					break;
+
+				// Polar Star
 				case 4:
 					ActBullet_PoleStar(&gBul[i], 1);
 					break;
@@ -2276,6 +2298,8 @@
 				case 6:
 					ActBullet_PoleStar(&gBul[i], 3);
 					break;
+
+				// Fireball
 				case 7:
 					ActBullet_FireBall(&gBul[i], 1);
 					break;
@@ -2285,6 +2309,8 @@
 				case 9:
 					ActBullet_FireBall(&gBul[i], 3);
 					break;
+
+				// Machine Gun
 				case 10:
 					ActBullet_MachineGun(&gBul[i], 1);
 					break;
@@ -2294,6 +2320,8 @@
 				case 12:
 					ActBullet_MachineGun(&gBul[i], 3);
 					break;
+
+				// Missile Launcher
 				case 13:
 					ActBullet_Missile(&gBul[i], 1);
 					break;
@@ -2303,6 +2331,8 @@
 				case 15:
 					ActBullet_Missile(&gBul[i], 3);
 					break;
+
+				// Missile Launcher explosion
 				case 16:
 					ActBullet_Bom(&gBul[i], 1);
 					break;
@@ -2312,6 +2342,8 @@
 				case 18:
 					ActBullet_Bom(&gBul[i], 3);
 					break;
+
+				// Bubbler
 				case 19:
 					ActBullet_Bubblin1(&gBul[i]);
 					break;
@@ -2321,15 +2353,23 @@
 				case 21:
 					ActBullet_Bubblin3(&gBul[i]);
 					break;
+
+				// Bubbler level 3 spines
 				case 22:
 					ActBullet_Spine(&gBul[i]);
 					break;
+
+				// Blade slashes
 				case 23:
 					ActBullet_Edge(&gBul[i]);
 					break;
+
+				// Falling spike that deals 127 damage
 				case 24:
 					ActBullet_Drop(&gBul[i]);
 					break;
+
+				// Blade
 				case 25:
 					ActBullet_Sword1(&gBul[i]);
 					break;
@@ -2339,6 +2379,8 @@
 				case 27:
 					ActBullet_Sword3(&gBul[i]);
 					break;
+
+				// Super Missile Launcher
 				case 28:
 					ActBullet_SuperMissile(&gBul[i], 1);
 					break;
@@ -2348,6 +2390,8 @@
 				case 30:
 					ActBullet_SuperMissile(&gBul[i], 3);
 					break;
+
+				// Super Missile Launcher explosion
 				case 31:
 					ActBullet_SuperBom(&gBul[i], 1);
 					break;
@@ -2357,6 +2401,8 @@
 				case 33:
 					ActBullet_SuperBom(&gBul[i], 3);
 					break;
+
+				// Nemesis
 				case 34:	// Identical to case 43
 					ActBullet_Nemesis(&gBul[i], 1);
 					break;
@@ -2366,6 +2412,8 @@
 				case 36:
 					ActBullet_Nemesis(&gBul[i], 3);
 					break;
+
+				// Spur
 				case 37:
 					ActBullet_Spur(&gBul[i], 1);
 					break;
@@ -2375,6 +2423,8 @@
 				case 39:
 					ActBullet_Spur(&gBul[i], 3);
 					break;
+
+				// Spur trail
 				case 40:
 					ActBullet_SpurTail(&gBul[i], 1);
 					break;
@@ -2384,12 +2434,18 @@
 				case 42:
 					ActBullet_SpurTail(&gBul[i], 3);
 					break;
+
+				// Curly's Nemesis
 				case 43:	// Identical to case 34
 					ActBullet_Nemesis(&gBul[i], 1);
 					break;
+
+				// Screen-nuke that kills all enemies
 				case 44:
 					ActBullet_EnemyClear(&gBul[i]);
 					break;
+
+				// Whimsical Star
 				case 45:
 					ActBullet_Star(&gBul[i]);
 					break;
--- a/src/Draw.cpp
+++ b/src/Draw.cpp
@@ -7,7 +7,7 @@
 
 #include "WindowsWrapper.h"
 
-#include "Backends/Platform.h"
+#include "Backends/Misc.h"
 #include "Backends/Rendering.h"
 #include "Bitmap.h"
 #include "CommonDefines.h"
@@ -32,9 +32,9 @@
 int magnification;
 BOOL fullscreen;
 
-static Backend_Surface *framebuffer;
+static RenderBackend_Surface *framebuffer;
 
-static Backend_Surface *surf[SURFACE_ID_MAX];
+static RenderBackend_Surface *surf[SURFACE_ID_MAX];
 
 static FontObject *font;
 
@@ -59,12 +59,12 @@
 			return FALSE;
 
 		// Framerate limiter
-		timeNow = PlatformBackend_GetTicks();
+		timeNow = Backend_GetTicks();
 
 		if (timeNow >= timePrev + 20)
 			break;
 
-		PlatformBackend_Delay(1);
+		Backend_Delay(1);
 	}
 
 	if (timeNow >= timePrev + 100)
@@ -72,7 +72,7 @@
 	else
 		timePrev += 20;
 
-	Backend_DrawScreen();
+	RenderBackend_DrawScreen();
 
 	if (RestoreSurfaces())
 	{
@@ -106,7 +106,7 @@
 			break;
 	}
 
-	framebuffer = Backend_Init(title, width, height, fullscreen);
+	framebuffer = RenderBackend_Init(title, width, height, fullscreen);
 
 	if (framebuffer == NULL)
 		return FALSE;
@@ -123,7 +123,7 @@
 	{
 		if (surf[i] != NULL)
 		{
-			Backend_FreeSurface(surf[i]);
+			RenderBackend_FreeSurface(surf[i]);
 			surf[i] = NULL;
 		}
 	}
@@ -130,7 +130,7 @@
 
 	framebuffer = NULL;
 
-	Backend_Deinit();
+	RenderBackend_Deinit();
 
 	memset(surface_metadata, 0, sizeof(surface_metadata));
 }
@@ -140,7 +140,7 @@
 	// Release the surface we want to release
 	if (surf[s] != NULL)
 	{
-		Backend_FreeSurface(surf[s]);
+		RenderBackend_FreeSurface(surf[s]);
 		surf[s] = NULL;
 	}
 
@@ -151,7 +151,7 @@
 {
 	// IF YOU WANT TO ADD HD SPRITES, THIS IS THE CODE YOU SHOULD EDIT
 	unsigned int pitch;
-	unsigned char *pixels = Backend_LockSurface(surf[surf_no], &pitch, width * magnification, height * magnification);
+	unsigned char *pixels = RenderBackend_LockSurface(surf[surf_no], &pitch, width * magnification, height * magnification);
 
 	if (magnification == 1)
 	{
@@ -192,7 +192,7 @@
 		}
 	}
 
-	Backend_UnlockSurface(surf[surf_no], width * magnification, height * magnification);
+	RenderBackend_UnlockSurface(surf[surf_no], width * magnification, height * magnification);
 
 	return TRUE;
 }
@@ -218,7 +218,7 @@
 	if (image_buffer == NULL)
 		return FALSE;
 
-	surf[surf_no] = Backend_CreateSurface(width * magnification, height * magnification);
+	surf[surf_no] = RenderBackend_CreateSurface(width * magnification, height * magnification);
 
 	if (surf[surf_no] == NULL)
 	{
@@ -228,7 +228,7 @@
 
 	if (!ScaleAndUploadSurface(image_buffer, width, height, surf_no))
 	{
-		Backend_FreeSurface(surf[surf_no]);
+		RenderBackend_FreeSurface(surf[surf_no]);
 		FreeBitmap(image_buffer);
 		return FALSE;
 	}
@@ -280,7 +280,7 @@
 		return FALSE;
 	}
 
-	surf[surf_no] = Backend_CreateSurface(width * magnification, height * magnification);
+	surf[surf_no] = RenderBackend_CreateSurface(width * magnification, height * magnification);
 
 	if (surf[surf_no] == NULL)
 	{
@@ -290,7 +290,7 @@
 
 	if (!ScaleAndUploadSurface(image_buffer, width, height, surf_no))
 	{
-		Backend_FreeSurface(surf[surf_no]);
+		RenderBackend_FreeSurface(surf[surf_no]);
 		FreeBitmap(image_buffer);
 		return FALSE;
 	}
@@ -391,7 +391,7 @@
 	if (surf[surf_no] != NULL)
 		return FALSE;
 
-	surf[surf_no] = Backend_CreateSurface(bxsize * magnification, bysize * magnification);
+	surf[surf_no] = RenderBackend_CreateSurface(bxsize * magnification, bysize * magnification);
 
 	if (surf[surf_no] == NULL)
 		return FALSE;
@@ -418,7 +418,7 @@
 	scaled_rect.right = rect->right * magnification;
 	scaled_rect.bottom = rect->bottom * magnification;
 
-	Backend_Blit(framebuffer, &scaled_rect, surf[surf_no], scaled_rect.left, scaled_rect.top, FALSE);
+	RenderBackend_Blit(framebuffer, &scaled_rect, surf[surf_no], scaled_rect.left, scaled_rect.top, FALSE);
 }
 
 void PutBitmap3(const RECT *rcView, int x, int y, const RECT *rect, SurfaceID surf_no) // Transparency
@@ -450,7 +450,7 @@
 	rcWork.right *= magnification;
 	rcWork.bottom *= magnification;
 
-	Backend_Blit(surf[surf_no], &rcWork, framebuffer, x * magnification, y * magnification, TRUE);
+	RenderBackend_Blit(surf[surf_no], &rcWork, framebuffer, x * magnification, y * magnification, TRUE);
 }
 
 void PutBitmap4(const RECT *rcView, int x, int y, const RECT *rect, SurfaceID surf_no) // No Transparency
@@ -482,7 +482,7 @@
 	rcWork.right *= magnification;
 	rcWork.bottom *= magnification;
 
-	Backend_Blit(surf[surf_no], &rcWork, framebuffer, x * magnification, y * magnification, FALSE);
+	RenderBackend_Blit(surf[surf_no], &rcWork, framebuffer, x * magnification, y * magnification, FALSE);
 }
 
 void Surface2Surface(int x, int y, const RECT *rect, int to, int from)
@@ -494,7 +494,7 @@
 	rcWork.right = rect->right * magnification;
 	rcWork.bottom = rect->bottom * magnification;
 
-	Backend_Blit(surf[from], &rcWork, surf[to], x * magnification, y * magnification, TRUE);
+	RenderBackend_Blit(surf[from], &rcWork, surf[to], x * magnification, y * magnification, TRUE);
 }
 
 unsigned long GetCortBoxColor(unsigned long col)
@@ -515,7 +515,7 @@
 	const unsigned char green = (col >> 8) & 0xFF;
 	const unsigned char blue = (col >> 16) & 0xFF;
 
-	Backend_ColourFill(framebuffer, &dst_rect, red, green, blue);
+	RenderBackend_ColourFill(framebuffer, &dst_rect, red, green, blue);
 }
 
 void CortBox2(const RECT *rect, unsigned long col, SurfaceID surf_no)
@@ -532,7 +532,7 @@
 	const unsigned char green = (col >> 8) & 0xFF;
 	const unsigned char blue = (col >> 16) & 0xFF;
 
-	Backend_ColourFill(surf[surf_no], &dst_rect, red, green, blue);
+	RenderBackend_ColourFill(surf[surf_no], &dst_rect, red, green, blue);
 }
 
 BOOL DummiedOutLogFunction(int unknown)
@@ -560,10 +560,10 @@
 	if (framebuffer == NULL)
 		return surfaces_regenerated;
 
-	if (Backend_IsSurfaceLost(framebuffer))
+	if (RenderBackend_IsSurfaceLost(framebuffer))
 	{
 		++surfaces_regenerated;
-		Backend_RestoreSurface(framebuffer);
+		RenderBackend_RestoreSurface(framebuffer);
 		DummiedOutLogFunction(0x62);
 	}
 
@@ -571,10 +571,10 @@
 	{
 		if (surf[s] != NULL)
 		{
-			if (Backend_IsSurfaceLost(surf[s]))
+			if (RenderBackend_IsSurfaceLost(surf[s]))
 			{
 				++surfaces_regenerated;
-				Backend_RestoreSurface(surf[s]);
+				RenderBackend_RestoreSurface(surf[s]);
 				DummiedOutLogFunction(0x30 + s);
 
 				if (!surface_metadata[s].bSystem)
--- a/src/Font.cpp
+++ b/src/Font.cpp
@@ -32,7 +32,7 @@
 	int x;
 	int y;
 	int x_advance;
-	Backend_Glyph *backend;
+	RenderBackend_Glyph *backend;
 
 	struct CachedGlyph *next;
 } CachedGlyph;
@@ -1014,7 +1014,7 @@
 				break;
 		}
 
-		glyph->backend = Backend_LoadGlyph(bitmap.buffer, bitmap.width, bitmap.rows, bitmap.pitch);
+		glyph->backend = RenderBackend_LoadGlyph(bitmap.buffer, bitmap.width, bitmap.rows, bitmap.pitch);
 
 		FT_Bitmap_Done(font_object->library, &bitmap);
 	}
@@ -1029,7 +1029,7 @@
 	{
 		CachedGlyph *next_glyph = glyph->next;
 
-		Backend_UnloadGlyph(glyph->backend);
+		RenderBackend_UnloadGlyph(glyph->backend);
 		free(glyph);
 
 		glyph = next_glyph;
@@ -1093,13 +1093,13 @@
 	return font_object;
 }
 
-void DrawText(FontObject *font_object, Backend_Surface *surface, int x, int y, unsigned long colour, const char *string)
+void DrawText(FontObject *font_object, RenderBackend_Surface *surface, int x, int y, unsigned long colour, const char *string)
 {
 	if (font_object != NULL)
 	{
 		const unsigned char colour_channels[3] = {(unsigned char)colour, (unsigned char)(colour >> 8), (unsigned char)(colour >> 16)};
 
-		Backend_PrepareToDrawGlyphs(surface, colour_channels);
+		RenderBackend_PrepareToDrawGlyphs(surface, colour_channels);
 
 		unsigned int pen_x = 0;
 
@@ -1124,13 +1124,13 @@
 				const int letter_y = y + glyph->y;
 
 				if (glyph->backend != NULL)
-					Backend_DrawGlyph(glyph->backend, letter_x, letter_y);
+					RenderBackend_DrawGlyph(glyph->backend, letter_x, letter_y);
 
 				pen_x += glyph->x_advance;
 			}
 		}
 
-		Backend_FlushGlyphs();
+		RenderBackend_FlushGlyphs();
 	}
 }
 
--- a/src/Font.h
+++ b/src/Font.h
@@ -8,5 +8,5 @@
 
 FontObject* LoadFontFromData(const unsigned char *data, size_t data_size, unsigned int cell_width, unsigned int cell_height);
 FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigned int cell_height);
-void DrawText(FontObject *font_object, Backend_Surface *surface, int x, int y, unsigned long colour, const char *string);
+void DrawText(FontObject *font_object, RenderBackend_Surface *surface, int x, int y, unsigned long colour, const char *string);
 void UnloadFont(FontObject *font_object);
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -6,7 +6,7 @@
 
 #include "WindowsWrapper.h"
 
-#include "Backends/Platform.h"
+#include "Backends/Misc.h"
 #include "ArmsItem.h"
 #include "Back.h"
 #include "Boss.h"
@@ -214,8 +214,8 @@
 		++gCounter;
 	}
 
-	wait = PlatformBackend_GetTicks();
-	while (PlatformBackend_GetTicks() < wait + 500)
+	wait = Backend_GetTicks();
+	while (Backend_GetTicks() < wait + 500)
 	{
 		CortBox(&grcGame, 0x000000);
 		PutFramePerSecound();
@@ -460,8 +460,8 @@
 	ChangeMusic(MUS_SILENCE);
 
 	// Black screen when option is selected
-	wait = PlatformBackend_GetTicks();
-	while (PlatformBackend_GetTicks() < wait + 1000)
+	wait = Backend_GetTicks();
+	while (Backend_GetTicks() < wait + 1000)
 	{
 		CortBox(&grcGame, 0);
 		PutFramePerSecound();
@@ -691,9 +691,9 @@
 	if (!LoadGenericData())
 	{
 #ifdef JAPANESE
-		PlatformBackend_ShowMessageBox("エラー", "汎用ファイルが読めない");
+		Backend_ShowMessageBox("エラー", "汎用ファイルが読めない");
 #else
-		PlatformBackend_ShowMessageBox("Error", "Couldn't read general purpose files");
+		Backend_ShowMessageBox("Error", "Couldn't read general purpose files");
 #endif
 
 		return FALSE;
@@ -707,9 +707,9 @@
 	if (!LoadNpcTable(path))
 	{
 #ifdef JAPANESE
-		PlatformBackend_ShowMessageBox("エラー", "NPCテーブルが読めない");
+		Backend_ShowMessageBox("エラー", "NPCテーブルが読めない");
 #else
-		PlatformBackend_ShowMessageBox("Error", "Couldn't read the NPC table");
+		Backend_ShowMessageBox("Error", "Couldn't read the NPC table");
 #endif
 
 		return FALSE;
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -7,7 +7,7 @@
 
 #include "WindowsWrapper.h"
 
-#include "Backends/Platform.h"
+#include "Backends/Misc.h"
 #include "Backends/Rendering.h"
 #include "Bitmap.h"
 #include "CommonDefines.h"
@@ -64,11 +64,11 @@
 
 	if (need_new_base_tick)
 	{
-		base_tick = PlatformBackend_GetTicks();
+		base_tick = Backend_GetTicks();
 		need_new_base_tick = FALSE;
 	}
 
-	current_tick = PlatformBackend_GetTicks();
+	current_tick = Backend_GetTicks();
 	++current_frame;
 
 	if (base_tick + 1000 <= current_tick)
@@ -88,10 +88,10 @@
 
 	int i;
 
-	PlatformBackend_Init();
+	Backend_Init();
 
 	// Get executable's path
-	if (!PlatformBackend_GetBasePath(gModulePath))
+	if (!Backend_GetBasePath(gModulePath))
 	{
 		// Fall back on argv[0] if the backend cannot provide a path
 		strcpy(gModulePath, argv[0]);
@@ -222,7 +222,7 @@
 			{
 				if (!StartDirectDraw(lpWindowName, windowWidth, windowHeight, 0))
 				{
-					PlatformBackend_Deinit();
+					Backend_Deinit();
 					return EXIT_FAILURE;
 				}
 			}
@@ -230,7 +230,7 @@
 			{
 				if (!StartDirectDraw(lpWindowName, windowWidth, windowHeight, 1))
 				{
-					PlatformBackend_Deinit();
+					Backend_Deinit();
 					return EXIT_FAILURE;
 				}
 			}
@@ -254,7 +254,7 @@
 		#ifdef FIX_BUGS
 			if (!StartDirectDraw(lpWindowName, windowWidth, windowHeight, 2))
 			{
-				PlatformBackend_Deinit();
+				Backend_Deinit();
 				return EXIT_FAILURE;
 			}
 		#else
@@ -264,7 +264,7 @@
 
 			bFullscreen = TRUE;
 
-			PlatformBackend_HideMouse();
+			Backend_HideMouse();
 			break;
 	}
 
@@ -282,7 +282,7 @@
 
 	if (window_icon_rgb_pixels != NULL)
 	{
-		PlatformBackend_SetWindowIcon(window_icon_rgb_pixels, window_icon_width, window_icon_height);
+		Backend_SetWindowIcon(window_icon_rgb_pixels, window_icon_width, window_icon_height);
 		FreeBitmap(window_icon_rgb_pixels);
 	}
 #endif
@@ -296,7 +296,7 @@
 
 	if (cursor_rgb_pixels != NULL)
 	{
-		PlatformBackend_SetCursor(cursor_rgb_pixels, cursor_width, cursor_height);
+		Backend_SetCursor(cursor_rgb_pixels, cursor_width, cursor_height);
 		FreeBitmap(cursor_rgb_pixels);
 	}
 
@@ -319,7 +319,7 @@
 	// Draw to screen
 	if (!Flip_SystemTask())
 	{
-		PlatformBackend_Deinit();
+		Backend_Deinit();
 		return EXIT_SUCCESS;
 	}
 
@@ -345,7 +345,7 @@
 	EndDirectSound();
 	EndDirectDraw();
 
-	PlatformBackend_Deinit();
+	Backend_Deinit();
 
 	return EXIT_SUCCESS;
 }
@@ -379,8 +379,180 @@
 
 BOOL SystemTask(void)
 {
-	if (!PlatformBackend_SystemTask())
+	if (!Backend_SystemTask())
 		return FALSE;
+
+	for (unsigned int i = 0; i < BACKEND_KEYBOARD_TOTAL; ++i)
+	{
+		if ((backend_keyboard_state[i] ^ backend_previous_keyboard_state[i]) & backend_keyboard_state[i])
+		{
+			switch (i)
+			{
+				case BACKEND_KEYBOARD_ESCAPE:
+					gKey |= KEY_ESCAPE;
+					break;
+
+				case BACKEND_KEYBOARD_W:
+					gKey |= KEY_MAP;
+					break;
+
+				case BACKEND_KEYBOARD_LEFT:
+					gKey |= KEY_LEFT;
+					break;
+
+				case BACKEND_KEYBOARD_RIGHT:
+					gKey |= KEY_RIGHT;
+					break;
+
+				case BACKEND_KEYBOARD_UP:
+					gKey |= KEY_UP;
+					break;
+
+				case BACKEND_KEYBOARD_DOWN:
+					gKey |= KEY_DOWN;
+					break;
+
+				case BACKEND_KEYBOARD_X:
+					gKey |= KEY_X;
+					break;
+
+				case BACKEND_KEYBOARD_Z:
+					gKey |= KEY_Z;
+					break;
+
+				case BACKEND_KEYBOARD_S:
+					gKey |= KEY_ARMS;
+					break;
+
+				case BACKEND_KEYBOARD_A:
+					gKey |= KEY_ARMSREV;
+					break;
+
+				case BACKEND_KEYBOARD_LEFT_SHIFT:
+				case BACKEND_KEYBOARD_RIGHT_SHIFT:
+					gKey |= KEY_SHIFT;
+					break;
+
+				case BACKEND_KEYBOARD_F1:
+					gKey |= KEY_F1;
+					break;
+
+				case BACKEND_KEYBOARD_F2:
+					gKey |= KEY_F2;
+					break;
+
+				case BACKEND_KEYBOARD_Q:
+					gKey |= KEY_ITEM;
+					break;
+
+				case BACKEND_KEYBOARD_COMMA:
+					gKey |= KEY_ALT_LEFT;
+					break;
+
+				case BACKEND_KEYBOARD_PERIOD:
+					gKey |= KEY_ALT_DOWN;
+					break;
+
+				case BACKEND_KEYBOARD_FORWARD_SLASH:
+					gKey |= KEY_ALT_RIGHT;
+					break;
+
+				case BACKEND_KEYBOARD_L:
+					gKey |= KEY_L;
+					break;
+
+				case BACKEND_KEYBOARD_EQUALS:
+					gKey |= KEY_PLUS;
+					break;
+
+				case BACKEND_KEYBOARD_F5:
+					gbUseJoystick = FALSE;
+					break;
+			}
+		}
+		else if ((backend_keyboard_state[i] ^ backend_previous_keyboard_state[i]) & backend_previous_keyboard_state[i])
+		{
+			switch (i)
+			{
+				case BACKEND_KEYBOARD_ESCAPE:
+					gKey &= ~KEY_ESCAPE;
+					break;
+
+				case BACKEND_KEYBOARD_W:
+					gKey &= ~KEY_MAP;
+					break;
+
+				case BACKEND_KEYBOARD_LEFT:
+					gKey &= ~KEY_LEFT;
+					break;
+
+				case BACKEND_KEYBOARD_RIGHT:
+					gKey &= ~KEY_RIGHT;
+					break;
+
+				case BACKEND_KEYBOARD_UP:
+					gKey &= ~KEY_UP;
+					break;
+
+				case BACKEND_KEYBOARD_DOWN:
+					gKey &= ~KEY_DOWN;
+					break;
+
+				case BACKEND_KEYBOARD_X:
+					gKey &= ~KEY_X;
+					break;
+
+				case BACKEND_KEYBOARD_Z:
+					gKey &= ~KEY_Z;
+					break;
+
+				case BACKEND_KEYBOARD_S:
+					gKey &= ~KEY_ARMS;
+					break;
+
+				case BACKEND_KEYBOARD_A:
+					gKey &= ~KEY_ARMSREV;
+					break;
+
+				case BACKEND_KEYBOARD_LEFT_SHIFT:
+				case BACKEND_KEYBOARD_RIGHT_SHIFT:
+					gKey &= ~KEY_SHIFT;
+					break;
+
+				case BACKEND_KEYBOARD_F1:
+					gKey &= ~KEY_F1;
+					break;
+
+				case BACKEND_KEYBOARD_F2:
+					gKey &= ~KEY_F2;
+					break;
+
+				case BACKEND_KEYBOARD_Q:
+					gKey &= ~KEY_ITEM;
+					break;
+
+				case BACKEND_KEYBOARD_COMMA:
+					gKey &= ~KEY_ALT_LEFT;
+					break;
+
+				case BACKEND_KEYBOARD_PERIOD:
+					gKey &= ~KEY_ALT_DOWN;
+					break;
+
+				case BACKEND_KEYBOARD_FORWARD_SLASH:
+					gKey &= ~KEY_ALT_RIGHT;
+					break;
+
+				case BACKEND_KEYBOARD_L:
+					gKey &= ~KEY_L;
+					break;
+
+				case BACKEND_KEYBOARD_EQUALS:
+					gKey &= ~KEY_PLUS;
+					break;
+			}
+		}
+	}
 
 	// Run joystick code
 	if (gbUseJoystick)
--- a/src/NpcAct000.cpp
+++ b/src/NpcAct000.cpp
@@ -1314,8 +1314,8 @@
 				npc->ani_no = 3;
 				npc->ym = -0x800;
 				npc->bits |= NPC_IGNORE_SOLIDITY;
-				DeleteNpCharCode(150, 0);
-				DeleteNpCharCode(117, 0);
+				DeleteNpCharCode(150, FALSE);
+				DeleteNpCharCode(117, FALSE);
 				SetNpChar(355, 0, 0, 0, 0, 0, npc, 0x100);
 				SetNpChar(355, 0, 0, 0, 0, 1, npc, 0x100);
 			}
--- a/src/NpcAct160.cpp
+++ b/src/NpcAct160.cpp
@@ -51,7 +51,7 @@
 
 			if (npc->flag & 8)
 			{
-				DeleteNpCharCode(161, 1);
+				DeleteNpCharCode(161, TRUE);
 
 				for (i = 0; i < 4; ++i)
 					SetNpChar(4, npc->x + (Random(-12, 12) * 0x200), npc->y + (Random(-12, 12) * 0x200), Random(-341, 341), Random(-0x600, 0), 0, NULL, 0x100);
@@ -245,7 +245,7 @@
 	switch (npc->act_no)
 	{
 		case 0:
-			DeleteNpCharCode(161, 1);
+			DeleteNpCharCode(161, TRUE);
 			PlaySoundObject(72, 1);
 
 			for (i = 0; i < 10; ++i)
@@ -315,7 +315,7 @@
 			if (++npc->count1 < 60)
 				break;
 
-			DeleteNpCharCode(161, 1);
+			DeleteNpCharCode(161, TRUE);
 			npc->cond = 0;
 
 			break;
--- a/src/NpcAct240.cpp
+++ b/src/NpcAct240.cpp
@@ -778,7 +778,7 @@
 			npc->xm = 0;
 			npc->ym = 0;
 
-			DeleteNpCharCode(252, 1);
+			DeleteNpCharCode(252, TRUE);
 
 			SetNpChar(4, npc->x, npc->y, 0, 0, 0, NULL, 0x100);
 			SetNpChar(4, npc->x, npc->y, 0, 0, 0, NULL, 0x100);
--- a/src/NpcAct260.cpp
+++ b/src/NpcAct260.cpp
@@ -1003,7 +1003,7 @@
 			break;
 
 		case 500:
-			DeleteNpCharCode(269, 1);
+			DeleteNpCharCode(269, TRUE);
 			npc->bits &= ~NPC_SHOOTABLE;
 			npc->ani_no = 4;
 			npc->ym += 0x20;
--- a/src/NpcAct280.cpp
+++ b/src/NpcAct280.cpp
@@ -116,7 +116,7 @@
 		case 21:
 			if (++npc->act_wait > 250)
 			{
-				DeleteNpCharCode(270, 0);
+				DeleteNpCharCode(270, FALSE);
 				npc->act_no = 22;
 			}
 
@@ -689,7 +689,7 @@
 			npc->view.top = 16 * 0x200;
 			npc->view.back = 16 * 0x200;
 			npc->view.front = 16 * 0x200;
-			DeleteNpCharCode(257, 1);
+			DeleteNpCharCode(257, TRUE);
 			break;
 
 		case 20:
--- a/src/NpcAct300.cpp
+++ b/src/NpcAct300.cpp
@@ -1339,7 +1339,7 @@
 			npc->ani_no = 8;
 			npc->tgt_x = npc->x;
 			npc->damage = 0;
-			DeleteNpCharCode(315, 1);
+			DeleteNpCharCode(315, TRUE);
 			// Fallthrough
 		case 501:
 			npc->ym += 0x20;
--- a/src/Profile.cpp
+++ b/src/Profile.cpp
@@ -6,7 +6,7 @@
 
 #include "WindowsWrapper.h"
 
-#include "Backends/Platform.h"
+#include "Backends/Misc.h"
 #include "ArmsItem.h"
 #include "BossLife.h"
 #include "Fade.h"
@@ -247,9 +247,9 @@
 	if (!TransferStage(13, 200, 10, 8))
 	{
 #ifdef JAPANESE
-		PlatformBackend_ShowMessageBox("エラー", "ステージの読み込みに失敗");
+		Backend_ShowMessageBox("エラー", "ステージの読み込みに失敗");
 #else
-		PlatformBackend_ShowMessageBox("Error", "Failed to load stage");
+		Backend_ShowMessageBox("Error", "Failed to load stage");
 #endif
 
 		return FALSE;
--- a/src/TextScr.cpp
+++ b/src/TextScr.cpp
@@ -6,7 +6,7 @@
 
 #include "WindowsWrapper.h"
 
-#include "Backends/Platform.h"
+#include "Backends/Misc.h"
 #include "ArmsItem.h"
 #include "Boss.h"
 #include "BossLife.h"
@@ -726,9 +726,9 @@
 						if (!TransferStage(z, w, x, y))
 						{
 							#ifdef JAPANESE
-							PlatformBackend_ShowMessageBox("エラー", "ステージの読み込みに失敗");
+							Backend_ShowMessageBox("エラー", "ステージの読み込みに失敗");
 							#else
-							PlatformBackend_ShowMessageBox("Error", "Failed to load stage");
+							Backend_ShowMessageBox("Error", "Failed to load stage");
 							#endif
 
 							return enum_ESCRETURN_exit;
@@ -1098,7 +1098,7 @@
 					else if (IS_COMMAND('D','N','A'))
 					{
 						z = GetTextScriptNo(gTS.p_read + 4);
-						DeleteNpCharCode(z, 1);
+						DeleteNpCharCode(z, TRUE);
 						gTS.p_read += 8;
 					}
 					else if (IS_COMMAND('B','O','A'))
@@ -1283,10 +1283,10 @@
 						char str_0[0x40];
 						#ifdef JAPANESE
 						sprintf(str_0, "不明のコード:<%c%c%c", gTS.data[gTS.p_read + 1], gTS.data[gTS.p_read + 2], gTS.data[gTS.p_read + 3]);
-						PlatformBackend_ShowMessageBox("エラー", str_0);
+						Backend_ShowMessageBox("エラー", str_0);
 						#else
 						sprintf(str_0, "Unknown code:<%c%c%c", gTS.data[gTS.p_read + 1], gTS.data[gTS.p_read + 2], gTS.data[gTS.p_read + 3]);
-						PlatformBackend_ShowMessageBox("Error", str_0);
+						Backend_ShowMessageBox("Error", str_0);
 						#endif
 
 						return enum_ESCRETURN_exit;