shithub: cstory

Download patch

ref: 68040d621576f67759d2c6092540b627a6f15c46
parent: 79ec91c85156980bb4ec7d652c21ae6d233015c5
parent: 44544a65d23de1c3d618c65198a22fc3b51ea107
author: Clownacy <Clownacy@users.noreply.github.com>
date: Tue Oct 20 14:34:00 EDT 2020

Merge pull request #144 from ccawley2011/RISC-OS-portable

RISC OS port

diff: cannot open b/assets/riscos//null: file does not exist: 'b/assets/riscos//null'
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,7 @@
 /obj
 
 # Exclude the (recommended) CMake build directory
-/build
+/build*
 
 # Exclude executables
 /game_english/CSE2_debug.exe
@@ -15,6 +15,7 @@
 /game_english/DoConfig
 /game_english/CSE2_debug.rpx
 /game_english/CSE2.rpx
+/game_english/\!CSE2
 /game_japanese/CSE2_debug.exe
 /game_japanese/DoConfig_debug.exe
 /game_japanese/CSE2.exe
@@ -25,6 +26,7 @@
 /game_japanese/DoConfig
 /game_japanese/CSE2_debug.rpx
 /game_japanese/CSE2.rpx
+/game_japanese/\!CSE2
 
 # Exclude MSVC debug data
 /game_english/CSE2_debug.ilk
@@ -96,9 +98,6 @@
 ###################
 # Portable branch #
 ###################
-
-# Exclude Wii U build directory
-/buildwiiu
 
 # Exclude converted resource files
 /src/Resource
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,8 +25,8 @@
 option(FREETYPE_FONTS "Use FreeType2 to render the DejaVu Mono (English) or Migu1M (Japanese) fonts, instead of using pre-rendered copies of Courier New (English) and MS Gothic (Japanese)" OFF)
 
 set(BACKEND_RENDERER "SDLTexture" CACHE STRING "Which renderer the game should use: 'OpenGL3' for an OpenGL 3.2 renderer, 'OpenGLES2' for an OpenGL ES 2.0 renderer, 'SDLTexture' for SDL2's hardware-accelerated Texture API, 'SDLSurface' for SDL2's software-rendered Surface API, 'Wii U' for the Wii U's hardware-accelerated GX2 API, '3DS' for the 3DS's hardware accelerated Citro2D/Citro3D API, or 'Software' for a handwritten software renderer")
-set(BACKEND_AUDIO "SDL2" CACHE STRING "Which audio backend the game should use: 'SDL2', 'miniaudio', 'WiiU-Hardware', 'WiiU-Software', '3DS-Hardware', '3DS-Software', or 'Null'")
-set(BACKEND_PLATFORM "SDL2" CACHE STRING "Which platform backend the game should use: 'SDL2', 'GLFW3', 'WiiU', '3DS', or 'Null'")
+set(BACKEND_AUDIO "SDL2" CACHE STRING "Which audio backend the game should use: 'SDL2', 'SDL1', 'miniaudio', 'WiiU-Hardware', 'WiiU-Software', '3DS-Hardware', '3DS-Software', or 'Null'")
+set(BACKEND_PLATFORM "SDL2" CACHE STRING "Which platform backend the game should use: 'SDL2', 'SDL1', 'GLFW3', 'WiiU', '3DS', or 'Null'")
 
 option(LTO "Enable link-time optimisation" OFF)
 option(PKG_CONFIG_STATIC_LIBS "On platforms with pkg-config, static-link the dependencies (good for Windows builds, so you don't need to bundle DLL files)" OFF)
@@ -336,6 +336,14 @@
 		"src/Backends/Audio/SoftwareMixer/Backend.h"
 		"src/Backends/Audio/SoftwareMixer/SDL2.cpp"
 	)
+elseif(BACKEND_AUDIO MATCHES "SDL1")
+	target_sources(CSE2 PRIVATE
+		"src/Backends/Audio/SoftwareMixer.cpp"
+		"src/Backends/Audio/SoftwareMixer/Mixer.cpp"
+		"src/Backends/Audio/SoftwareMixer/Mixer.h"
+		"src/Backends/Audio/SoftwareMixer/Backend.h"
+		"src/Backends/Audio/SoftwareMixer/SDL1.cpp"
+	)
 elseif(BACKEND_AUDIO MATCHES "miniaudio")
 	target_sources(CSE2 PRIVATE
 		"src/Backends/Audio/SoftwareMixer.cpp"
@@ -393,10 +401,16 @@
 
 if(BACKEND_PLATFORM MATCHES "SDL2")
 	target_sources(CSE2 PRIVATE
-		"src/Backends/Controller/SDL2.cpp"
+		"src/Backends/Controller/SDL.cpp"
 		"src/Backends/Platform/SDL2.cpp"
-		"src/Backends/Shared/SDL2.h"
+		"src/Backends/Shared/SDL.h"
 	)
+elseif(BACKEND_PLATFORM MATCHES "SDL1")
+	target_sources(CSE2 PRIVATE
+		"src/Backends/Controller/SDL.cpp"
+		"src/Backends/Platform/SDL1.cpp"
+		"src/Backends/Shared/SDL.h"
+	)
 elseif(BACKEND_PLATFORM MATCHES "GLFW3")
 	target_sources(CSE2 PRIVATE
 		"src/Backends/Controller/GLFW3.cpp"
@@ -428,6 +442,10 @@
 elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "SDLSurface")
 elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "Software")
 	target_sources(CSE2 PRIVATE "src/Backends/Rendering/Window/Software/SDL2.cpp")
+elseif(BACKEND_PLATFORM MATCHES "SDL1" AND BACKEND_RENDERER MATCHES "OpenGL3")
+	target_sources(CSE2 PRIVATE "src/Backends/Rendering/Window/OpenGL3/SDL1.cpp")
+elseif(BACKEND_PLATFORM MATCHES "SDL1" AND BACKEND_RENDERER MATCHES "Software")
+	target_sources(CSE2 PRIVATE "src/Backends/Rendering/Window/Software/SDL1.cpp")
 elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "OpenGL3")
 	target_sources(CSE2 PRIVATE "src/Backends/Rendering/Window/OpenGL3/GLFW3.cpp")
 elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "OpenGLES2")
@@ -599,6 +617,45 @@
 	endif()
 endif()
 
+if(BACKEND_PLATFORM MATCHES "SDL1" OR BACKEND_AUDIO MATCHES "SDL1")
+	if(BACKEND_PLATFORM MATCHES "SDL2" OR BACKEND_AUDIO MATCHES "SDL2")
+		message(FATAL_ERROR "SDL1 and SDL2 cannot be used simultaneously!")
+	endif()
+
+	find_package(SDL 1.2.15)
+
+	if (PKG_CONFIG_FOUND)
+		pkg_check_modules(sdl QUIET IMPORTED_TARGET sdl)
+	endif()
+
+	if(TARGET PkgConfig::sdl)
+		# pkg-config
+		if (PKG_CONFIG_STATIC_LIBS)
+			message(STATUS "Using system SDL1 (pkg-config, static)")
+			# Do not link libSDLmain.a, otherwise we get weird linker errors about SDL_main not being found.
+			# We don't need SDL's WinMain->main shim anyway, so we can just ignore it.
+			list(REMOVE_ITEM sdl_STATIC_CFLAGS "-Dmain=SDL_main")
+			list(REMOVE_ITEM sdl_STATIC_LDFLAGS "-lSDLmain")
+			target_compile_options(CSE2 PRIVATE ${sdl_STATIC_CFLAGS})
+			target_link_libraries(CSE2 PRIVATE ${sdl_STATIC_LDFLAGS})
+		else()
+			message(STATUS "Using system SDL1 (pkg-config, dynamic)")
+			# Do not link libSDLmain.a, otherwise we get weird linker errors about SDL_main not being found.
+			# We don't need SDL's WinMain->main shim anyway, so we can just ignore it.
+			list(REMOVE_ITEM sdl_CFLAGS "-Dmain=SDL_main")
+			list(REMOVE_ITEM sdl_LDFLAGS "-lSDLmain")
+			target_compile_options(CSE2 PRIVATE ${sdl_CFLAGS})
+			target_link_libraries(CSE2 PRIVATE ${sdl_LDFLAGS})
+		endif()
+	elseif(SDL_FOUND)
+		message(STATUS "Using system SDL1 (CMake)")
+		target_include_directories(CSE2 PRIVATE ${SDL_INCLUDE_DIR})
+		target_link_libraries(CSE2 PRIVATE ${SDL_LIBRARY})
+	else()
+		message(FATAL_ERROR "SDL1 not installed!")
+	endif()
+endif()
+
 if(FREETYPE_FONTS)
 	if(NOT FORCE_LOCAL_LIBS)
 		find_package(Freetype)
@@ -717,4 +774,8 @@
 		RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${BUILD_DIRECTORY}
 		RUNTIME_OUTPUT_DIRECTORY_DEBUG ${BUILD_DIRECTORY}
 	)
+endif()
+
+if(RISCOS)
+	include(RISCOSApp)
 endif()
--- /dev/null
+++ b/assets/riscos/!Boot,feb
@@ -1,0 +1,2 @@
+Set CSE2$Dir <Obey$Dir>
+IconSprites <CSE2$Dir>.!Sprites
--- /dev/null
+++ b/assets/riscos/!Run,feb
@@ -1,0 +1,2 @@
+Set CSE2$Dir <Obey$Dir>
+Run <CSE2$Dir>.CSE2 ><CSE2$Dir>.Log 2>&1
binary files /dev/null b/assets/riscos/!Sprites,ff9 differ
--- /dev/null
+++ b/cmake/RISCOSApp.cmake
@@ -1,0 +1,22 @@
+# Use the following commands to build for RISC OS:
+# cmake -B build-riscos -DCMAKE_BUILD_TYPE=Release -DBACKEND_PLATFORM=SDL1 -DBACKEND_RENDERER=Software -DBACKEND_AUDIO=SDL1 -DDOCONFIG=OFF -DCMAKE_TOOLCHAIN_FILE=$GCCSDK_INSTALL_ENV/toolchain-riscos.cmake -DRISCOS=ON -DPKG_CONFIG_STATIC_LIBS=ON
+# cmake --build build-riscos
+# (cd game_english && $GCCSDK_INSTALL_ENV/bin/zip -,9r cse2-riscos.zip \!CSE2)
+
+function(elf_to_aif)
+	cmake_parse_arguments(ELFTOAIF "" "TARGET;OUTPUT" "" ${ARGN})
+	get_filename_component(ELFTOAIF_OUTPUT_DIR "${ELFTOAIF_OUTPUT}" DIRECTORY)
+	add_custom_command(OUTPUT "${ELFTOAIF_OUTPUT}"
+	                   COMMAND ${CMAKE_COMMAND} -E make_directory ${ELFTOAIF_OUTPUT_DIR}
+	                   COMMAND elf2aif $<TARGET_FILE:${ELFTOAIF_TARGET}> ${ELFTOAIF_OUTPUT}
+	                   DEPENDS ${ELFTOAIF_TARGET})
+	add_custom_target(${ELFTOAIF_TARGET}-aif ALL DEPENDS ${ELFTOAIF_OUTPUT})
+endfunction(elf_to_aif)
+
+elf_to_aif(TARGET CSE2 OUTPUT ${BUILD_DIRECTORY}/!CSE2/CSE2,ff8)
+
+configure_file(${ASSETS_DIRECTORY}/riscos/!Boot,feb ${BUILD_DIRECTORY}/!CSE2/!Boot,feb COPYONLY)
+configure_file(${ASSETS_DIRECTORY}/riscos/!Run,feb ${BUILD_DIRECTORY}/!CSE2/!Run,feb COPYONLY)
+configure_file(${ASSETS_DIRECTORY}/riscos/!Sprites,ff9 ${BUILD_DIRECTORY}/!CSE2/!Sprites,ff9 COPYONLY)
+configure_file(${BUILD_DIRECTORY}/licence.txt ${BUILD_DIRECTORY}/!CSE2/Licence COPYONLY)
+file(COPY ${BUILD_DIRECTORY}/data DESTINATION ${BUILD_DIRECTORY}/!CSE2)
--- /dev/null
+++ b/src/Backends/Audio/SoftwareMixer/SDL1.cpp
@@ -1,0 +1,113 @@
+#include "Backend.h"
+
+#include <stddef.h>
+#include <string.h>
+#include <string>
+
+#include "SDL.h"
+
+#include "../../Misc.h"
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+static void (*parent_callback)(long *stream, size_t frames_total);
+
+static void Callback(void *user_data, Uint8 *stream_uint8, int len)
+{
+	(void)user_data;
+
+	short *stream = (short*)stream_uint8;
+	const size_t frames_total = len / sizeof(short) / 2;
+
+	size_t frames_done = 0;
+
+	while (frames_done != frames_total)
+	{
+		long mix_buffer[0x800 * 2];	// 2 because stereo
+
+		size_t subframes = MIN(0x800, frames_total - frames_done);
+
+		memset(mix_buffer, 0, subframes * sizeof(long) * 2);
+
+		parent_callback(mix_buffer, subframes);
+
+		for (size_t i = 0; i < subframes * 2; ++i)
+		{
+			if (mix_buffer[i] > 0x7FFF)
+				*stream++ = 0x7FFF;
+			else if (mix_buffer[i] < -0x7FFF)
+				*stream++ = -0x7FFF;
+			else
+				*stream++ = mix_buffer[i];
+		}
+
+		frames_done += subframes;
+	}
+}
+
+unsigned long SoftwareMixerBackend_Init(void (*callback)(long *stream, size_t frames_total))
+{
+	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
+	{
+		std::string errorMessage = std::string("'SDL_InitSubSystem(SDL_INIT_AUDIO)' failed: ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (SDL1 audio backend)", errorMessage.c_str());
+		return false;
+	}
+
+	SDL_AudioSpec specification;
+	specification.freq = 48000;
+	specification.format = AUDIO_S16;
+	specification.channels = 2;
+	specification.samples = 0x400;	// Roughly 10 milliseconds for 48000Hz
+	specification.callback = Callback;
+	specification.userdata = NULL;
+
+	SDL_AudioSpec obtained_specification;
+	if (SDL_OpenAudio(&specification, &obtained_specification) != 0)
+	{
+		std::string error_message = std::string("'SDL_OpenAudio' failed: ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (SDL1 audio backend)", error_message.c_str());
+		return false;
+	}
+
+	char driver[20];
+	Backend_PrintInfo("Selected SDL audio driver: %s", SDL_AudioDriverName(driver, 20));
+
+	parent_callback = callback;
+
+	return obtained_specification.freq;
+}
+
+void SoftwareMixerBackend_Deinit(void)
+{
+	SDL_CloseAudio();
+
+	SDL_QuitSubSystem(SDL_INIT_AUDIO);
+}
+
+bool SoftwareMixerBackend_Start(void)
+{
+	SDL_PauseAudio(0);
+
+	return true;
+}
+
+void SoftwareMixerBackend_LockMixerMutex(void)
+{
+	SDL_LockAudio();
+}
+
+void SoftwareMixerBackend_UnlockMixerMutex(void)
+{
+	SDL_UnlockAudio();
+}
+
+void SoftwareMixerBackend_LockOrganyaMutex(void)
+{
+	SDL_LockAudio();
+}
+
+void SoftwareMixerBackend_UnlockOrganyaMutex(void)
+{
+	SDL_UnlockAudio();
+}
--- /dev/null
+++ b/src/Backends/Controller/SDL.cpp
@@ -1,0 +1,212 @@
+#include "../Controller.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "SDL.h"
+
+#include "../Misc.h"
+#include "../Shared/SDL.h"
+
+#define DEADZONE 10000
+
+static SDL_Joystick *joystick;
+
+static Sint16 *axis_neutrals;
+
+bool ControllerBackend_Init(void)
+{
+	if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
+	{
+		Backend_PrintError("Couldn't initialise joystick SDL subsystem: %s", SDL_GetError());
+		return false;
+	}
+
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+	if (SDL_NumJoysticks() > 0)
+		ControllerBackend_JoystickConnect(0);
+#endif
+
+	return true;
+}
+
+void ControllerBackend_Deinit(void)
+{
+	if (joystick != NULL)
+	{
+		SDL_JoystickClose(joystick);
+		joystick = NULL;
+	}
+
+	SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+}
+
+bool ControllerBackend_GetJoystickStatus(bool **buttons, unsigned int *button_count, short **axes, unsigned int *axis_count)
+{
+	if (joystick == NULL)
+		return false;
+
+	int total_sdl_buttons = SDL_JoystickNumButtons(joystick);
+	if (total_sdl_buttons < 0)
+	{
+		total_sdl_buttons = 0;
+		Backend_PrintError("Failed to get number of buttons on joystick: %s", SDL_GetError());
+	}
+
+	int total_sdl_axes = SDL_JoystickNumAxes(joystick);
+	if (total_sdl_axes < 0)
+	{
+		total_sdl_axes = 0;
+		Backend_PrintError("Failed to get number of general axis controls on joystick: %s", SDL_GetError());
+	}
+
+	int total_sdl_hats = SDL_JoystickNumHats(joystick);
+	if (total_sdl_hats < 0)
+	{
+		total_sdl_hats = 0;
+		Backend_PrintError("Failed to get number of POV hats on joystick: %s", SDL_GetError());
+	}
+
+	*button_count = total_sdl_buttons + total_sdl_axes * 2 + total_sdl_hats * 4;
+	*axis_count = total_sdl_axes;
+
+	static bool *button_buffer = NULL;
+	static short *axis_buffer = NULL;
+
+	bool *new_button_buffer = (bool*)realloc(button_buffer, *button_count * sizeof(bool));
+
+	if (new_button_buffer == NULL)
+		return false;
+
+	button_buffer = new_button_buffer;
+
+	short *new_axis_buffer = (short*)realloc(axis_buffer, *axis_count * sizeof(short));
+
+	if (new_axis_buffer == NULL)
+		return false;
+
+	axis_buffer = new_axis_buffer;
+
+	//////////////////////////
+	// Handle button inputs //
+	//////////////////////////
+
+	unsigned int current_button = 0;
+
+	// Start with the joystick buttons
+	for (int i = 0; i < total_sdl_buttons; ++i)
+		button_buffer[current_button++] = SDL_JoystickGetButton(joystick, i);
+
+	// Then the joystick axes
+	for (int i = 0; i < total_sdl_axes; ++i)
+	{
+		Sint16 axis = SDL_JoystickGetAxis(joystick, i);
+
+		button_buffer[current_button++] = axis < axis_neutrals[i] - DEADZONE;
+		button_buffer[current_button++] = axis > axis_neutrals[i] + DEADZONE;
+	}
+
+	// Then the joystick hats
+	for (int i = 0; i < total_sdl_hats; ++i)
+	{
+		Uint8 hat = SDL_JoystickGetHat(joystick, i);
+
+		button_buffer[current_button++] = hat == SDL_HAT_UP || hat == SDL_HAT_LEFTUP || hat == SDL_HAT_RIGHTUP;
+		button_buffer[current_button++] = hat == SDL_HAT_RIGHT || hat == SDL_HAT_RIGHTUP || hat == SDL_HAT_RIGHTDOWN;
+		button_buffer[current_button++] = hat == SDL_HAT_DOWN || hat == SDL_HAT_LEFTDOWN || hat == SDL_HAT_RIGHTDOWN;
+		button_buffer[current_button++] = hat == SDL_HAT_LEFT || hat == SDL_HAT_LEFTUP || hat == SDL_HAT_LEFTDOWN;
+	}
+
+	*buttons = button_buffer;
+
+	////////////////////////
+	// Handle axis inputs //
+	////////////////////////
+
+	for (int i = 0; i < total_sdl_axes; ++i)
+		axis_buffer[i] = SDL_JoystickGetAxis(joystick, i);
+
+	*axes = axis_buffer;
+
+	return true;
+}
+
+void ControllerBackend_JoystickConnect(Sint32 joystick_id)
+{
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	const char *joystick_name = SDL_JoystickNameForIndex(joystick_id);
+#else
+	const char *joystick_name = SDL_JoystickName(joystick_id);
+#endif
+
+	if (joystick_name != NULL)
+	{
+		Backend_PrintInfo("Joystick #%d connected - %s", joystick_id, joystick_name);
+	}
+	else
+	{
+		Backend_PrintError("Couldn't get joystick name: %s", SDL_GetError());
+		Backend_PrintInfo("Joystick #%d connected - Name unknown", joystick_id);
+	}
+
+	if (joystick == NULL)
+	{
+		joystick = SDL_JoystickOpen(joystick_id);
+
+		if (joystick != NULL)
+		{
+			int total_axes = SDL_JoystickNumAxes(joystick);
+			if (total_axes < 0)
+				Backend_PrintError("Couldn't get number of general axis control on connected joystick: %s", SDL_GetError());
+
+			int total_buttons = SDL_JoystickNumButtons(joystick);
+			if (total_buttons < 0)
+				Backend_PrintError("Couldn't get number of buttons on connected joystick: %s", SDL_GetError());
+
+			if (total_axes >= 2 && total_buttons >= 6)
+			{
+				Backend_PrintInfo("Joystick #%d selected", joystick_id);
+
+				// Set up neutral axes
+				axis_neutrals = (Sint16*)malloc(sizeof(Sint16) * total_axes);
+
+				if (axis_neutrals != NULL)
+				{
+					for (int i = 0; i < total_axes; ++i)
+						axis_neutrals[i] = SDL_JoystickGetAxis(joystick, i);
+
+					return;
+				}
+				else
+				{
+					Backend_PrintError("Couldn't allocate memory for neutral axes");
+				}
+			}
+
+			SDL_JoystickClose(joystick);
+			joystick = NULL;
+		}
+		else
+		{
+			Backend_PrintError("Couldn't open joystick for use: %s", SDL_GetError());
+		}
+	}
+}
+
+void ControllerBackend_JoystickDisconnect(Sint32 joystick_id)
+{
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	SDL_JoystickID current_joystick_id = SDL_JoystickInstanceID(joystick);
+	if (current_joystick_id < 0)
+		Backend_PrintError("Couldn't get instance ID for current joystick: %s", SDL_GetError());
+
+	if (joystick_id == current_joystick_id)
+	{
+		Backend_PrintInfo("Joystick #%d disconnected", joystick_id);
+		SDL_JoystickClose(joystick);
+		joystick = NULL;
+
+		free(axis_neutrals);
+	}
+#endif
+}
--- a/src/Backends/Controller/SDL2.cpp
+++ /dev/null
@@ -1,201 +1,0 @@
-#include "../Controller.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "SDL.h"
-
-#include "../Misc.h"
-#include "../Shared/SDL2.h"
-
-#define DEADZONE 10000
-
-static SDL_Joystick *joystick;
-
-static Sint16 *axis_neutrals;
-
-bool ControllerBackend_Init(void)
-{
-	if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
-	{
-		Backend_PrintError("Couldn't initialise joystick SDL subsystem: %s", SDL_GetError());
-		return false;
-	}
-
-	return true;
-}
-
-void ControllerBackend_Deinit(void)
-{
-	if (joystick != NULL)
-	{
-		SDL_JoystickClose(joystick);
-		joystick = NULL;
-	}
-
-	SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
-}
-
-bool ControllerBackend_GetJoystickStatus(bool **buttons, unsigned int *button_count, short **axes, unsigned int *axis_count)
-{
-	if (joystick == NULL)
-		return false;
-
-	int total_sdl_buttons = SDL_JoystickNumButtons(joystick);
-	if (total_sdl_buttons < 0)
-	{
-		total_sdl_buttons = 0;
-		Backend_PrintError("Failed to get number of buttons on joystick: %s", SDL_GetError());
-	}
-
-	int total_sdl_axes = SDL_JoystickNumAxes(joystick);
-	if (total_sdl_axes < 0)
-	{
-		total_sdl_axes = 0;
-		Backend_PrintError("Failed to get number of general axis controls on joystick: %s", SDL_GetError());
-	}
-
-	int total_sdl_hats = SDL_JoystickNumHats(joystick);
-	if (total_sdl_hats < 0)
-	{
-		total_sdl_hats = 0;
-		Backend_PrintError("Failed to get number of POV hats on joystick: %s", SDL_GetError());
-	}
-
-	*button_count = total_sdl_buttons + total_sdl_axes * 2 + total_sdl_hats * 4;
-	*axis_count = total_sdl_axes;
-
-	static bool *button_buffer = NULL;
-	static short *axis_buffer = NULL;
-
-	bool *new_button_buffer = (bool*)realloc(button_buffer, *button_count * sizeof(bool));
-
-	if (new_button_buffer == NULL)
-		return false;
-
-	button_buffer = new_button_buffer;
-
-	short *new_axis_buffer = (short*)realloc(axis_buffer, *axis_count * sizeof(short));
-
-	if (new_axis_buffer == NULL)
-		return false;
-
-	axis_buffer = new_axis_buffer;
-
-	//////////////////////////
-	// Handle button inputs //
-	//////////////////////////
-
-	unsigned int current_button = 0;
-
-	// Start with the joystick buttons
-	for (int i = 0; i < total_sdl_buttons; ++i)
-		button_buffer[current_button++] = SDL_JoystickGetButton(joystick, i);
-
-	// Then the joystick axes
-	for (int i = 0; i < total_sdl_axes; ++i)
-	{
-		Sint16 axis = SDL_JoystickGetAxis(joystick, i);
-
-		button_buffer[current_button++] = axis < axis_neutrals[i] - DEADZONE;
-		button_buffer[current_button++] = axis > axis_neutrals[i] + DEADZONE;
-	}
-
-	// Then the joystick hats
-	for (int i = 0; i < total_sdl_hats; ++i)
-	{
-		Uint8 hat = SDL_JoystickGetHat(joystick, i);
-
-		button_buffer[current_button++] = hat == SDL_HAT_UP || hat == SDL_HAT_LEFTUP || hat == SDL_HAT_RIGHTUP;
-		button_buffer[current_button++] = hat == SDL_HAT_RIGHT || hat == SDL_HAT_RIGHTUP || hat == SDL_HAT_RIGHTDOWN;
-		button_buffer[current_button++] = hat == SDL_HAT_DOWN || hat == SDL_HAT_LEFTDOWN || hat == SDL_HAT_RIGHTDOWN;
-		button_buffer[current_button++] = hat == SDL_HAT_LEFT || hat == SDL_HAT_LEFTUP || hat == SDL_HAT_LEFTDOWN;
-	}
-
-	*buttons = button_buffer;
-
-	////////////////////////
-	// Handle axis inputs //
-	////////////////////////
-
-	for (int i = 0; i < total_sdl_axes; ++i)
-		axis_buffer[i] = SDL_JoystickGetAxis(joystick, i);
-
-	*axes = axis_buffer;
-
-	return true;
-}
-
-void ControllerBackend_JoystickConnect(Sint32 joystick_id)
-{
-	const char *joystick_name = SDL_JoystickNameForIndex(joystick_id);
-
-	if (joystick_name != NULL)
-	{
-		Backend_PrintInfo("Joystick #%d connected - %s", joystick_id, joystick_name);
-	}
-	else
-	{
-		Backend_PrintError("Couldn't get joystick name: %s", SDL_GetError());
-		Backend_PrintInfo("Joystick #%d connected - Name unknown", joystick_id);
-	}
-
-	if (joystick == NULL)
-	{
-		joystick = SDL_JoystickOpen(joystick_id);
-
-		if (joystick != NULL)
-		{
-			int total_axes = SDL_JoystickNumAxes(joystick);
-			if (total_axes < 0)
-				Backend_PrintError("Couldn't get number of general axis control on connected joystick: %s", SDL_GetError());
-
-			int total_buttons = SDL_JoystickNumButtons(joystick);
-			if (total_buttons < 0)
-				Backend_PrintError("Couldn't get number of buttons on connected joystick: %s", SDL_GetError());
-
-			if (total_axes >= 2 && total_buttons >= 6)
-			{
-				Backend_PrintInfo("Joystick #%d selected", joystick_id);
-
-				// Set up neutral axes
-				axis_neutrals = (Sint16*)malloc(sizeof(Sint16) * total_axes);
-
-				if (axis_neutrals != NULL)
-				{
-					for (int i = 0; i < total_axes; ++i)
-						axis_neutrals[i] = SDL_JoystickGetAxis(joystick, i);
-
-					return;
-				}
-				else
-				{
-					Backend_PrintError("Couldn't allocate memory for neutral axes");
-				}
-			}
-
-			SDL_JoystickClose(joystick);
-			joystick = NULL;
-		}
-		else
-		{
-			Backend_PrintError("Couldn't open joystick for use: %s", SDL_GetError());
-		}
-	}
-}
-
-void ControllerBackend_JoystickDisconnect(Sint32 joystick_id)
-{
-	SDL_JoystickID current_joystick_id = SDL_JoystickInstanceID(joystick);
-	if (current_joystick_id < 0)
-		Backend_PrintError("Couldn't get instance ID for current joystick: %s", SDL_GetError());
-
-	if (joystick_id == current_joystick_id)
-	{
-		Backend_PrintInfo("Joystick #%d disconnected", joystick_id);
-		SDL_JoystickClose(joystick);
-		joystick = NULL;
-
-		free(axis_neutrals);
-	}
-}
--- /dev/null
+++ b/src/Backends/Platform/SDL1.cpp
@@ -1,0 +1,257 @@
+#include "../Misc.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+#include "SDL.h"
+
+#include "../Rendering.h"
+#include "../../Attributes.h"
+
+#define DO_KEY(SDL_KEY, BACKEND_KEY) \
+	case SDL_KEY: \
+		keyboard_state[BACKEND_KEY] = event.key.type == SDL_KEYDOWN; \
+		break;
+
+static bool keyboard_state[BACKEND_KEYBOARD_TOTAL];
+
+static void (*window_focus_callback)(bool focus);
+
+bool Backend_Init(void (*drag_and_drop_callback_param)(const char *path), void (*window_focus_callback_param)(bool focus))
+{
+	window_focus_callback = window_focus_callback_param;
+
+	if (SDL_Init(SDL_INIT_VIDEO) == 0)
+	{
+		char driver[20];
+		if (SDL_VideoDriverName(driver, 20) != NULL)
+		{
+			Backend_PrintInfo("Selected SDL video driver: %s", driver);
+
+			return true;
+		}
+		else
+		{
+			Backend_PrintError("No SDL video driver initialized!");
+			SDL_Quit();
+		}
+	}
+	else
+	{
+		std::string error_message = std::string("Could not initialise SDL: ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error", error_message.c_str());
+	}
+
+	return false;
+}
+
+void Backend_Deinit(void)
+{
+	SDL_Quit();
+}
+
+void Backend_PostWindowCreation(void)
+{
+}
+
+bool Backend_GetPaths(std::string *module_path, std::string *data_path)
+{
+	(void)module_path;
+	(void)data_path;
+
+	return false;
+}
+
+void Backend_HideMouse(void)
+{
+	SDL_ShowCursor(SDL_DISABLE);
+}
+
+void Backend_SetWindowIcon(const unsigned char *rgb_pixels, size_t width, size_t height)
+{
+	SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)rgb_pixels, width, height, 24, width * 3, 0x0000FF, 0x00FF00, 0xFF0000, 0);
+
+	if (surface != NULL)
+	{
+		SDL_WM_SetIcon(surface, NULL);
+		SDL_FreeSurface(surface);
+	}
+	else
+	{
+		Backend_PrintError("Couldn't create RGB surface for window icon: %s", SDL_GetError());
+	}
+}
+
+void Backend_SetCursor(const unsigned char *rgb_pixels, size_t width, size_t height)
+{
+	(void)rgb_pixels;
+	(void)width;
+	(void)height;
+	// SDL1 only supports black and white cursors
+}
+
+void Backend_EnableDragAndDrop(void)
+{
+}
+
+bool Backend_SystemTask(bool active)
+{
+	if (!active)
+		if (!SDL_WaitEvent(NULL))
+			return false;
+
+	SDL_Event event;
+
+	while (SDL_PollEvent(&event))
+	{
+		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_ACTIVEEVENT:
+				if (event.active.state & SDL_APPINPUTFOCUS)
+				{
+					window_focus_callback(event.active.gain);
+				}
+
+				break;
+
+			case SDL_VIDEORESIZE:
+				RenderBackend_HandleWindowResize(event.resize.w, event.resize.h);
+				break;
+
+			case SDL_QUIT:
+				return false;
+		}
+	}
+
+	return true;
+}
+
+void Backend_GetKeyboardState(bool *out_keyboard_state)
+{
+	memcpy(out_keyboard_state, keyboard_state, sizeof(keyboard_state));
+}
+
+void Backend_ShowMessageBox(const char *title, const char *message)
+{
+	Backend_PrintInfo("ShowMessageBox - '%s' - '%s'\n", title, message);
+}
+
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...)
+{
+	va_list argumentList;
+	va_start(argumentList, format);
+	fputs("ERROR: ", stderr);
+	vfprintf(stderr, format, argumentList);
+	fputc('\n', stderr);
+	va_end(argumentList);
+}
+
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...)
+{
+	va_list argumentList;
+	va_start(argumentList, format);
+	fputs("INFO: ", stdout);
+	vfprintf(stdout, format, argumentList);
+	fputc('\n', stdout);
+	va_end(argumentList);
+}
+
+unsigned long Backend_GetTicks(void)
+{
+	return SDL_GetTicks();
+}
+
+void Backend_Delay(unsigned int ticks)
+{
+	SDL_Delay(ticks);
+}
--- a/src/Backends/Platform/SDL2.cpp
+++ b/src/Backends/Platform/SDL2.cpp
@@ -10,7 +10,7 @@
 #include "SDL.h"
 
 #include "../Rendering.h"
-#include "../Shared/SDL2.h"
+#include "../Shared/SDL.h"
 #include "../../Attributes.h"
 
 #define DO_KEY(SDL_KEY, BACKEND_KEY) \
--- a/src/Backends/Rendering/SDLSurface.cpp
+++ b/src/Backends/Rendering/SDLSurface.cpp
@@ -8,7 +8,7 @@
 #include "SDL.h"
 
 #include "../Misc.h"
-#include "../Shared/SDL2.h"
+#include "../Shared/SDL.h"
 
 typedef struct RenderBackend_Surface
 {
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -10,7 +10,7 @@
 #include "../../WindowsWrapper.h"
 
 #include "../Misc.h"
-#include "../Shared/SDL2.h"
+#include "../Shared/SDL.h"
 
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
--- /dev/null
+++ b/src/Backends/Rendering/Window/OpenGL3/SDL1.cpp
@@ -1,0 +1,52 @@
+#include "../OpenGL.h"
+
+#include <stddef.h>
+#include <string>
+
+#include <glad/glad.h>
+#include "SDL.h"
+
+#include "../../../Misc.h"
+
+bool WindowBackend_OpenGL_CreateWindow(const char *window_title, size_t *screen_width, size_t *screen_height, bool fullscreen)
+{
+	if (SDL_SetVideoMode(*screen_width, *screen_height, 0, SDL_RESIZABLE | SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)) != NULL)
+	{
+		SDL_WM_SetCaption(window_title, NULL);
+
+		if (gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
+		{
+			// Check if the platform supports OpenGL 3.2
+			if (GLAD_GL_VERSION_3_2)
+			{
+				Backend_PostWindowCreation();
+
+				return true;
+			}
+			else
+			{
+				Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Your system does not support OpenGL 3.2");
+			}
+		}
+		else
+		{
+			Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Couldn't load OpenGL functions");
+		}
+	}
+	else
+	{
+		std::string error_message = std::string("Could not create window: ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", error_message.c_str());
+	}
+
+	return false;
+}
+
+void WindowBackend_OpenGL_DestroyWindow(void)
+{
+}
+
+void WindowBackend_OpenGL_Display(void)
+{
+	SDL_GL_SwapBuffers();
+}
--- a/src/Backends/Rendering/Window/OpenGL3/SDL2.cpp
+++ b/src/Backends/Rendering/Window/OpenGL3/SDL2.cpp
@@ -9,7 +9,7 @@
 #include "SDL.h"
 
 #include "../../../Misc.h"
-#include "../../../Shared/SDL2.h"
+#include "../../../Shared/SDL.h"
 
 SDL_Window *window;
 
--- /dev/null
+++ b/src/Backends/Rendering/Window/Software/SDL1.cpp
@@ -1,0 +1,88 @@
+#include "../Software.h"
+
+#include <stddef.h>
+#include <string>
+
+#include "SDL.h"
+
+#include "../../../Misc.h"
+
+static int bits_per_pixel = 24;
+static Uint32 window_flags = SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_ANYFORMAT;
+
+static SDL_Surface *window_sdlsurface;
+static SDL_Surface *framebuffer_sdlsurface;
+
+bool WindowBackend_Software_CreateWindow(const char *window_title, size_t screen_width, size_t screen_height, bool fullscreen)
+{
+	if (fullscreen)
+		window_flags |= SDL_FULLSCREEN;
+	else
+		window_flags &= ~SDL_FULLSCREEN;
+
+	window_sdlsurface = SDL_SetVideoMode(screen_width, screen_height, bits_per_pixel, window_flags);
+	if (window_sdlsurface == NULL) {
+		Backend_PrintError("Couldn't create 24bpp window: %s", SDL_GetError());
+		bits_per_pixel = 32;
+		window_sdlsurface = SDL_SetVideoMode(screen_width, screen_height, bits_per_pixel, window_flags);
+	}
+
+	if (window_sdlsurface != NULL)
+	{
+		SDL_WM_SetCaption(window_title, NULL);
+		framebuffer_sdlsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, window_sdlsurface->w, window_sdlsurface->h, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0);
+
+		if (framebuffer_sdlsurface != NULL)
+		{
+			SDL_LockSurface(framebuffer_sdlsurface); // If this errors then oh dear
+
+			Backend_PostWindowCreation();
+
+			return true;
+		}
+		else
+		{
+			std::string error_message = std::string("Couldn't create framebuffer surface: ") + SDL_GetError();
+			Backend_ShowMessageBox("Fatal error (software rendering backend)", error_message.c_str());
+		}
+	}
+	else
+	{
+		std::string error_message = std::string("Couldn't create window: ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (software rendering backend)", error_message.c_str());
+	}
+
+	return false;
+}
+
+void WindowBackend_Software_DestroyWindow(void)
+{
+	SDL_FreeSurface(framebuffer_sdlsurface);
+}
+
+unsigned char* WindowBackend_Software_GetFramebuffer(size_t *pitch)
+{
+	*pitch = framebuffer_sdlsurface->pitch;
+
+	return (unsigned char*)framebuffer_sdlsurface->pixels;
+}
+
+void WindowBackend_Software_Display(void)
+{
+	SDL_UnlockSurface(framebuffer_sdlsurface);
+
+	if (SDL_BlitSurface(framebuffer_sdlsurface, NULL, window_sdlsurface, NULL) < 0)
+		Backend_PrintError("Couldn't blit framebuffer surface to window surface: %s", SDL_GetError());
+
+	SDL_LockSurface(framebuffer_sdlsurface); // If this errors then oh dear
+
+	if (SDL_Flip(window_sdlsurface) < 0)
+		Backend_PrintError("Couldn't copy window surface to the screen: %s", SDL_GetError());
+}
+
+void WindowBackend_Software_HandleWindowResize(size_t width, size_t height)
+{
+	window_sdlsurface = SDL_SetVideoMode(width, height, bits_per_pixel, window_flags);
+	if (window_sdlsurface == NULL)
+		Backend_PrintError("Couldn't get SDL surface associated with window: %s", SDL_GetError());
+}
--- a/src/Backends/Rendering/Window/Software/SDL2.cpp
+++ b/src/Backends/Rendering/Window/Software/SDL2.cpp
@@ -6,7 +6,7 @@
 #include "SDL.h"
 
 #include "../../../Misc.h"
-#include "../../../Shared/SDL2.h"
+#include "../../../Shared/SDL.h"
 
 SDL_Window *window;
 
--- /dev/null
+++ b/src/Backends/Shared/SDL.h
@@ -1,0 +1,10 @@
+#pragma once
+
+#include "SDL.h"
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+extern SDL_Window *window;
+#endif
+
+void ControllerBackend_JoystickConnect(Sint32 joystick_id);
+void ControllerBackend_JoystickDisconnect(Sint32 joystick_id);
--- a/src/Backends/Shared/SDL2.h
+++ /dev/null
@@ -1,8 +1,0 @@
-#pragma once
-
-#include "SDL.h"
-
-extern SDL_Window *window;
-
-void ControllerBackend_JoystickConnect(Sint32 joystick_id);
-void ControllerBackend_JoystickDisconnect(Sint32 joystick_id);
--- a/src/Config.cpp
+++ b/src/Config.cpp
@@ -65,6 +65,8 @@
 
 #ifdef _3DS
 	conf->display_mode = 1;
+#elif defined(__riscos__)
+	conf->display_mode = 2;
 #endif
 
 	// Reset joystick settings (as these can't simply be set to 0)