SDL: Add a barebones RISC OS video driver

From 25c71748ad7327da43ae9315969d2369610e3321 Mon Sep 17 00:00:00 2001
From: Cameron Cawley <[EMAIL REDACTED]>
Date: Thu, 13 Feb 2020 21:55:08 +0000
Subject: [PATCH] Add a barebones RISC OS video driver

---
 CMakeLists.txt                             |   7 +
 configure                                  |   9 +
 configure.ac                               |   7 +
 include/SDL_config.h.cmake                 |   1 +
 include/SDL_config.h.in                    |   1 +
 include/SDL_syswm.h                        |   3 +-
 src/video/SDL_sysvideo.h                   |   1 +
 src/video/SDL_video.c                      |  15 +-
 src/video/riscos/SDL_riscosevents.c        |  41 ++++
 src/video/riscos/SDL_riscosevents_c.h      |  33 +++
 src/video/riscos/SDL_riscosframebuffer.c   | 148 ++++++++++++
 src/video/riscos/SDL_riscosframebuffer_c.h |  33 +++
 src/video/riscos/SDL_riscosmessagebox.c    |  68 ++++++
 src/video/riscos/SDL_riscosmessagebox.h    |  29 +++
 src/video/riscos/SDL_riscosvideo.c         | 251 +++++++++++++++++++++
 src/video/riscos/SDL_riscosvideo.h         |  30 +++
 16 files changed, 675 insertions(+), 2 deletions(-)
 create mode 100644 src/video/riscos/SDL_riscosevents.c
 create mode 100644 src/video/riscos/SDL_riscosevents_c.h
 create mode 100644 src/video/riscos/SDL_riscosframebuffer.c
 create mode 100644 src/video/riscos/SDL_riscosframebuffer_c.h
 create mode 100644 src/video/riscos/SDL_riscosmessagebox.c
 create mode 100644 src/video/riscos/SDL_riscosmessagebox.h
 create mode 100644 src/video/riscos/SDL_riscosvideo.c
 create mode 100644 src/video/riscos/SDL_riscosvideo.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 807e529a6e..294e93c968 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2118,6 +2118,13 @@ elseif(RISCOS)
   set(SOURCE_FILES ${SOURCE_FILES} ${MISC_SOURCES})
   set(HAVE_SDL_MISC TRUE)
 
+  if(SDL_VIDEO)
+    set(SDL_VIDEO_DRIVER_RISCOS 1)
+    file(GLOB RISCOSVIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/riscos/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${RISCOSVIDEO_SOURCES})
+    set(HAVE_SDL_VIDEO TRUE)
+  endif()
+
   if(SDL_FILESYSTEM)
     set(SDL_FILESYSTEM_RISCOS 1)
     file(GLOB FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/riscos/*.c)
diff --git a/configure b/configure
index 060845a7fd..76990784f9 100755
--- a/configure
+++ b/configure
@@ -25794,6 +25794,15 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
         SOURCES="$SOURCES $srcdir/src/misc/riscos/*.c"
         have_misc=yes
 
+        # Set up files for the video library
+        if test x$enable_video = xyes; then
+
+$as_echo "#define SDL_VIDEO_DRIVER_RISCOS 1" >>confdefs.h
+
+            SOURCES="$SOURCES $srcdir/src/video/riscos/*.c"
+            have_video=yes
+            SUMMARY_video="${SUMMARY_video} riscos"
+        fi
         # Set up files for the filesystem library
         if test x$enable_filesystem = xyes; then
 
diff --git a/configure.ac b/configure.ac
index 3a71a16d59..b61d3f1060 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4277,6 +4277,13 @@ case "$host" in
         SOURCES="$SOURCES $srcdir/src/misc/riscos/*.c"
         have_misc=yes
 
+        # Set up files for the video library
+        if test x$enable_video = xyes; then
+            AC_DEFINE(SDL_VIDEO_DRIVER_RISCOS, 1, [ ])
+            SOURCES="$SOURCES $srcdir/src/video/riscos/*.c"
+            have_video=yes
+            SUMMARY_video="${SUMMARY_video} riscos"
+        fi
         # Set up files for the filesystem library
         if test x$enable_filesystem = xyes; then
             AC_DEFINE(SDL_FILESYSTEM_RISCOS, 1, [ ])
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
index 7fd73e5a7b..a0784f603f 100644
--- a/include/SDL_config.h.cmake
+++ b/include/SDL_config.h.cmake
@@ -392,6 +392,7 @@
 #cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@
 #cmakedefine SDL_VIDEO_DRIVER_OS2 @SDL_VIDEO_DRIVER_OS2@
 #cmakedefine SDL_VIDEO_DRIVER_QNX @SDL_VIDEO_DRIVER_QNX@
+#cmakedefine SDL_VIDEO_DRIVER_RISCOS @SDL_VIDEO_DRIVER_RISCOS@
 
 #cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@
 #cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@
diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in
index 35f5bd0b44..0bb904c13e 100644
--- a/include/SDL_config.h.in
+++ b/include/SDL_config.h.in
@@ -401,6 +401,7 @@
 #undef SDL_VIDEO_DRIVER_VIVANTE_VDK
 #undef SDL_VIDEO_DRIVER_OS2
 #undef SDL_VIDEO_DRIVER_QNX
+#undef SDL_VIDEO_DRIVER_RISCOS
 
 #undef SDL_VIDEO_RENDER_D3D
 #undef SDL_VIDEO_RENDER_D3D11
diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h
index 0936727b18..d25efc14b2 100644
--- a/include/SDL_syswm.h
+++ b/include/SDL_syswm.h
@@ -143,7 +143,8 @@ typedef enum
     SDL_SYSWM_VIVANTE,
     SDL_SYSWM_OS2,
     SDL_SYSWM_HAIKU,
-    SDL_SYSWM_KMSDRM
+    SDL_SYSWM_KMSDRM,
+    SDL_SYSWM_RISCOS
 } SDL_SYSWM_TYPE;
 
 /**
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 844a7a65e9..7e22d1b7a8 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -437,6 +437,7 @@ extern VideoBootStrap UIKIT_bootstrap;
 extern VideoBootStrap Android_bootstrap;
 extern VideoBootStrap PSP_bootstrap;
 extern VideoBootStrap VITA_bootstrap;
+extern VideoBootStrap RISCOS_bootstrap;
 extern VideoBootStrap RPI_bootstrap;
 extern VideoBootStrap KMSDRM_bootstrap;
 extern VideoBootStrap KMSDRM_LEGACY_bootstrap;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 18268a9430..fda2c47b32 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -100,6 +100,9 @@ static VideoBootStrap *bootstrap[] = {
 #if SDL_VIDEO_DRIVER_KMSDRM
     &KMSDRM_bootstrap,
 #endif
+#if SDL_VIDEO_DRIVER_RISCOS
+    &RISCOS_bootstrap,
+#endif
 #if SDL_VIDEO_DRIVER_RPI
     &RPI_bootstrap,
 #endif
@@ -4152,11 +4155,14 @@ SDL_IsScreenKeyboardShown(SDL_Window *window)
 #if SDL_VIDEO_DRIVER_OS2
 #include "os2/SDL_os2messagebox.h"
 #endif
+#if SDL_VIDEO_DRIVER_RISCOS
+#include "riscos/SDL_riscosmessagebox.h"
+#endif
 #if SDL_VIDEO_DRIVER_VITA
 #include "vita/SDL_vitamessagebox.h"
 #endif
 
-#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11 || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_HAIKU || SDL_VIDEO_DRIVER_OS2
+#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11 || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_HAIKU || SDL_VIDEO_DRIVER_OS2 || SDL_VIDEO_DRIVER_RISCOS
 static SDL_bool SDL_MessageboxValidForDriver(const SDL_MessageBoxData *messageboxdata, SDL_SYSWM_TYPE drivertype)
 {
     SDL_SysWMinfo info;
@@ -4276,6 +4282,13 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
         retval = 0;
     }
 #endif
+#if SDL_VIDEO_DRIVER_RISCOS
+    if (retval == -1 &&
+        SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_RISCOS) &&
+        RISCOS_ShowMessageBox(messageboxdata, buttonid) == 0) {
+        retval = 0;
+    }
+#endif
 #if SDL_VIDEO_DRIVER_VITA
     if (retval == -1 &&
         VITA_ShowMessageBox(messageboxdata, buttonid) == 0) {
diff --git a/src/video/riscos/SDL_riscosevents.c b/src/video/riscos/SDL_riscosevents.c
new file mode 100644
index 0000000000..3c428f51ec
--- /dev/null
+++ b/src/video/riscos/SDL_riscosevents.c
@@ -0,0 +1,41 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_RISCOS
+
+/* Being a null driver, there's no event stream. We just define stubs for
+   most of the API. */
+
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_riscosvideo.h"
+#include "SDL_riscosevents_c.h"
+
+void
+RISCOS_PumpEvents(_THIS)
+{
+    /* do nothing. */
+}
+
+#endif /* SDL_VIDEO_DRIVER_RISCOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosevents_c.h b/src/video/riscos/SDL_riscosevents_c.h
new file mode 100644
index 0000000000..373bb724ea
--- /dev/null
+++ b/src/video/riscos/SDL_riscosevents_c.h
@@ -0,0 +1,33 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_riscosevents_c_h_
+#define SDL_riscosevents_c_h_
+
+#include "../../SDL_internal.h"
+
+#include "SDL_riscosvideo.h"
+
+extern void RISCOS_PumpEvents(_THIS);
+
+#endif /* SDL_riscosevents_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosframebuffer.c b/src/video/riscos/SDL_riscosframebuffer.c
new file mode 100644
index 0000000000..7764c42374
--- /dev/null
+++ b/src/video/riscos/SDL_riscosframebuffer.c
@@ -0,0 +1,148 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_RISCOS
+
+#include "../SDL_sysvideo.h"
+#include "SDL_riscosframebuffer_c.h"
+#include "SDL_riscosvideo.h"
+
+#include <kernel.h>
+#include <swis.h>
+
+#define DUMMY_SURFACE   "_SDL_DummySurface"
+
+typedef struct {
+    Uint32 size;
+    Uint32 count;
+    Uint32 start;
+    Uint32 end;
+} sprite_area;
+
+int SDL_RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
+{
+    const char *sprite_name = "display";
+    int width, height, size, bytesPerRow;
+    unsigned int sprite_mode;
+    _kernel_oserror *error;
+    _kernel_swi_regs regs;
+    sprite_area *buffer;
+    Uint32 pixelformat;
+    SDL_DisplayMode mode;
+
+    /* Free the old framebuffer surface */
+    buffer = (sprite_area *) SDL_SetWindowData(window, DUMMY_SURFACE, NULL);
+    SDL_free(buffer);
+
+    /* Create a new one */
+    SDL_GetWindowSize(window, &width, &height);
+    SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(window), &mode);
+
+    if ((SDL_ISPIXELFORMAT_PACKED(mode.format) || SDL_ISPIXELFORMAT_ARRAY(mode.format))) {
+        pixelformat = mode.format;
+        sprite_mode = (unsigned int)mode.driverdata;
+    } else {
+        pixelformat = SDL_PIXELFORMAT_BGR888;
+        sprite_mode = (1 | (90 << 1) | (90 << 14) | (6 << 27));
+    }
+
+    bytesPerRow = SDL_BYTESPERPIXEL(pixelformat) * width;
+    if ((bytesPerRow & 3) != 0) {
+        bytesPerRow += 4 - (bytesPerRow & 3);
+    }
+    size = 60 + (bytesPerRow * height);
+
+    buffer = SDL_malloc(size);
+    if (!buffer) {
+        SDL_OutOfMemory();
+        return -1;
+    }
+
+    /* Initialise a sprite area */
+
+    buffer->size  = size;
+    buffer->start = 16;
+
+    regs.r[0] = 256+9;
+    regs.r[1] = (unsigned int)buffer;
+    error = _kernel_swi(OS_SpriteOp, &regs, &regs);
+    if (error != NULL) {
+        SDL_SetError("Unable to initialise sprite area: %s (%i)", error->errmess, error->errnum);
+        SDL_free(buffer);
+        return -1;
+    }
+
+    regs.r[0] = 256+15;
+    regs.r[1] = (unsigned int)buffer;
+    regs.r[2] = (unsigned int)sprite_name;
+    regs.r[3] = 0;
+    regs.r[4] = width;
+    regs.r[5] = height;
+    regs.r[6] = sprite_mode;
+    error = _kernel_swi(OS_SpriteOp, &regs, &regs);
+    if (error != NULL) {
+        SDL_SetError("Unable to create sprite: %s (%i)", error->errmess, error->errnum);
+        SDL_free(buffer);
+        return -1;
+    }
+
+    /* Save the info and return! */
+    SDL_SetWindowData(window, DUMMY_SURFACE, buffer);
+    *format = pixelformat;
+    *pixels = ((Uint8 *)buffer) + 60;
+    *pitch = bytesPerRow;
+
+    return 0;
+}
+
+int SDL_RISCOS_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+{
+    _kernel_swi_regs regs;
+    sprite_area *buffer;
+
+    buffer = (sprite_area *) SDL_GetWindowData(window, DUMMY_SURFACE);
+    if (!buffer) {
+        return SDL_SetError("Couldn't find sprite for window");
+    }
+
+    regs.r[0] = 512+52;
+    regs.r[1] = (unsigned int)buffer;
+    regs.r[2] = (unsigned int)buffer + buffer->start;
+    regs.r[3] = window->x * 2;
+    regs.r[4] = window->y * 2;
+    regs.r[5] = 0x50;
+    regs.r[6] = 0;
+    regs.r[7] = 0;
+    _kernel_swi(OS_SpriteOp, &regs, &regs);
+
+    return 0;
+}
+
+void SDL_RISCOS_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
+{
+    sprite_area *buffer = (sprite_area *) SDL_SetWindowData(window, DUMMY_SURFACE, NULL);
+    SDL_free(buffer);
+}
+
+#endif /* SDL_VIDEO_DRIVER_RISCOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosframebuffer_c.h b/src/video/riscos/SDL_riscosframebuffer_c.h
new file mode 100644
index 0000000000..196a33338d
--- /dev/null
+++ b/src/video/riscos/SDL_riscosframebuffer_c.h
@@ -0,0 +1,33 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_riscosframebuffer_c_h_
+#define SDL_riscosframebuffer_c_h_
+
+#include "../../SDL_internal.h"
+
+extern int SDL_RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
+extern int SDL_RISCOS_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
+extern void SDL_RISCOS_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
+
+#endif /* SDL_riscosframebuffer_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosmessagebox.c b/src/video/riscos/SDL_riscosmessagebox.c
new file mode 100644
index 0000000000..09ff4559e0
--- /dev/null
+++ b/src/video/riscos/SDL_riscosmessagebox.c
@@ -0,0 +1,68 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_RISCOS
+
+#include "SDL_messagebox.h"
+#include "SDL_riscosmessagebox.h"
+
+#include <kernel.h>
+#include <swis.h>
+
+int
+RISCOS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+    _kernel_swi_regs regs;
+    _kernel_oserror error;
+    char buttonstring[1024];
+    int i;
+
+    error.errnum = 0;
+    SDL_strlcpy(error.errmess, messageboxdata->message, 252);
+    regs.r[0] = (unsigned int)&error;
+
+    regs.r[1] = (1 << 8) | (1 << 4);
+    if (messageboxdata->flags == SDL_MESSAGEBOX_INFORMATION)
+        regs.r[1] |= (1 << 9);
+    else if (messageboxdata->flags == SDL_MESSAGEBOX_WARNING)
+        regs.r[1] |= (2 << 9);
+    regs.r[2] = (unsigned int)messageboxdata->title;
+    regs.r[3] = 0;
+    regs.r[4] = 0;
+
+    SDL_strlcpy(buttonstring, "" , 1024);
+    for (i = 0; i < messageboxdata->numbuttons; i++) {
+        SDL_strlcat(buttonstring, messageboxdata->buttons[i].text, 1024);
+        if (i + 1 < messageboxdata->numbuttons)
+            SDL_strlcat(buttonstring, ",", 1024);
+    }
+    regs.r[5] = (unsigned int)buttonstring;
+
+    _kernel_swi(Wimp_ReportError, &regs, &regs);
+
+    *buttonid = (regs.r[1] == 0) ? -1 : messageboxdata->buttons[regs.r[1] - 3].buttonid;
+    return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_RISCOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosmessagebox.h b/src/video/riscos/SDL_riscosmessagebox.h
new file mode 100644
index 0000000000..9895a4887b
--- /dev/null
+++ b/src/video/riscos/SDL_riscosmessagebox.h
@@ -0,0 +1,29 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_RISCOS
+
+extern int RISCOS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+#endif /* SDL_VIDEO_DRIVER_RISCOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosvideo.c b/src/video/riscos/SDL_riscosvideo.c
new file mode 100644
index 0000000000..d39a3df2c0
--- /dev/null
+++ b/src/video/riscos/SDL_riscosvideo.c
@@ -0,0 +1,251 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_RISCOS
+
+/* Dummy SDL video driver implementation; this is just enough to make an
+ *  SDL-based application THINK it's got a working video driver, for
+ *  applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it,
+ *  and also for use as a collection of stubs when porting SDL to a new
+ *  platform for which you haven't yet written a valid video driver.
+ *
+ * This is also a great way to determine bottlenecks: if you think that SDL
+ *  is a performance problem for a given platform, enable this driver, and
+ *  then see if your application runs faster without video overhead.
+ *
+ * Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion
+ *  of this was cut-and-pasted from Stephane Peter's work in the AAlib
+ *  SDL video driver.  Renamed to "DUMMY" by Sam Lantinga.
+ */
+
+#include "SDL_version.h"
+#include "SDL_video.h"
+#include "SDL_mouse.h"
+#include "SDL_syswm.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_riscosvideo.h"
+#include "SDL_riscosevents_c.h"
+#include "SDL_riscosframebuffer_c.h"
+
+#include <kernel.h>
+#include <swis.h>
+
+#define RISCOSVID_DRIVER_NAME "riscos"
+
+/* Initialization/Query functions */
+static int RISCOS_VideoInit(_THIS);
+static int RISCOS_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
+static void RISCOS_VideoQuit(_THIS);
+SDL_bool RISCOS_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info);
+
+/* RISC OS driver bootstrap functions */
+
+static void
+RISCOS_DeleteDevice(SDL_VideoDevice * device)
+{
+    SDL_free(device);
+}
+
+static SDL_VideoDevice *
+RISCOS_CreateDevice(int devindex)
+{
+    SDL_VideoDevice *device;
+
+    /* Initialize all variables that we clean on shutdown */
+    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+    if (!device) {
+        SDL_OutOfMemory();
+        return (0);
+    }
+
+    /* Set the function pointers */
+    device->VideoInit = RISCOS_VideoInit;
+    device->VideoQuit = RISCOS_VideoQuit;
+    device->SetDisplayMode = RISCOS_SetDisplayMode;
+    device->PumpEvents = RISCOS_PumpEvents;
+
+    device->GetWindowWMInfo = RISCOS_GetWindowWMInfo;
+
+    device->CreateWindowFramebuffer = SDL_RISCOS_CreateWindowFramebuffer;
+    device->UpdateWindowFramebuffer = SDL_RISCOS_UpdateWindowFramebuffer;
+    device->DestroyWindowFramebuffer = SDL_RISCOS_DestroyWindowFramebuffer;
+
+    device->free = RISCOS_DeleteDevice;
+
+    return device;
+}
+
+VideoBootStrap RISCOS_bootstrap = {
+    RISCOSVID_DRIVER_NAME, "SDL RISC OS video driver",
+    RISCOS_CreateDevice
+};
+
+enum {
+    MODE_FLAG_565 = 1 << 7,
+
+    MODE_FLAG_COLOUR_SPACE = 0xF << 12,
+
+    MODE_FLAG_TBGR = 0,
+    MODE_FLAG_TRGB = 1 << 14,
+    MODE_FLAG_ABGR = 1 << 15,
+    MODE_FLAG_ARGB = MODE_FLAG_TRGB | MODE_FLAG_ABGR
+};
+
+#define MODE_350(type, xdpi, ydpi) \
+        (1 | (xdpi << 1) | (ydpi << 14) | (type << 27))
+#define MODE_521(type, xeig, yeig, flags) \
+        (0x78000001 | (xeig << 4) | (yeig << 6) | (flags & 0xFF00) | (type << 20))
+
+static const struct {
+    SDL_PixelFormatEnum pixel_format;
+    int modeflags, ncolour, log2bpp, sprite_type;
+} mode_to_pixelformat[] = {
+    { SDL_PIXELFORMAT_INDEX1LSB, 0, 1, 0, 1 },
+    /* { SDL_PIXELFORMAT_INDEX2LSB, 0, 3, 1, 2 }, */
+    { SDL_PIXELFORMAT_INDEX4LSB, 0, 15, 2, 3 },
+    { SDL_PIXELFORMAT_INDEX8,    MODE_FLAG_565, 255, 3, 4 },
+    { SDL_PIXELFORMAT_BGR555,    MODE_FLAG_TBGR, 65535, 4, 5 },
+    { SDL_PIXELFORMAT_RGB555,    MODE_FLAG_TRGB, 65535, 4, 5 },
+    { SDL_PIXELFORMAT_ABGR1555,  MODE_FLAG_ABGR, 65535, 4, 5 },
+    { SDL_PIXELFORMAT_ARGB1555,  MODE_FLAG_ARGB, 65535, 4, 5 },
+    { SDL_PIXELFORMAT_BGR444,    MODE_FLAG_TBGR, 4095, 4, 16 },
+    { SDL_PIXELFORMAT_RGB444,    MODE_FLAG_TRGB, 4095, 4, 16 },
+    { SDL_PIXELFORMAT_ABGR4444,  MODE_FLAG_ABGR, 4095, 4, 16 },
+    { SDL_PIXELFORMAT_ARGB4444,  MODE_FLAG_ARGB, 4095, 4, 16 },
+    { SDL_PIXELFORMAT_BGR565,    MODE_FLAG_TBGR | MODE_FLAG_565, 65535, 4, 10 },
+    { SDL_PIXELFORMAT_RGB565,    MODE_FLAG_TRGB | MODE_FLAG_565, 65535, 4, 10 },
+    { SDL_PIXELFORMAT_BGR24,     MODE_FLAG_TBGR, 16777215, 6, 8 },
+    { SDL_PIXELFORMAT_RGB24,     MODE_FLAG_TRGB, 16777215, 6, 8 },
+    { SDL_PIXELFORMAT_BGR888,    MODE_FLAG_TBGR, -1, 5, 6 },
+    { SDL_PIXELFORMAT_RGB888,    MODE_FLAG_TRGB, -1, 5, 6 },
+    { SDL_PIXELFORMAT_ABGR8888,  MODE_FLAG_ABGR, -1, 5, 6 },
+    { SDL_PIXELFORMAT_ARGB8888,  MODE_FLAG_ARGB, -1, 5, 6 }
+};
+
+static int ReadModeVariable(int mode, int variable) {
+    _kernel_swi_regs regs;
+    regs.r[0] = mode;
+    regs.r[1] = variable;
+    _kernel_swi(OS_ReadModeVariable, &regs, &regs);
+    return regs.r[2];
+}
+
+SDL_PixelFormatEnum RISCOS_ModeToPixelFormat(int *mode) {
+    int i, log2bpp, ncolour, modeflags;
+    log2bpp = ReadModeVariable((int)mode, 9);
+    ncolour = ReadModeVariable((int)mode, 3);
+    modeflags = ReadModeVariable((int)mode, 0);
+
+    for (i = 0; i < SDL_arraysize(mode_to_pixelformat); i++) {
+        if (log2bpp == mode_to_pixelformat[i].log2bpp &&
+           (ncolour == mode_to_pixelformat[i].ncolour || ncolour == 0) &&
+           (modeflags & (MODE_FLAG_565 | MODE_FLAG_COLOUR_SPACE)) == mode_to_pixelformat[i].modeflags) {
+            return mode_to_pixelformat[i].pixel_format;
+        }
+    }
+
+    return SDL_PIXELFORMAT_UNKNOWN;
+}
+
+static void *copy_mode_block(int *storeBlock)
+{
+    int *outBlock;
+    int blockSize = (storeBlock[0] == 2) ? 7 : 5;
+    while(storeBlock[blockSize] != -1) {
+        blockSize += 2;
+    }
+    blockSize++;
+
+    outBlock = SDL_calloc(sizeof(int), blockSize);
+    SDL_memcpy(outBlock, storeBlock, sizeof(int) * blockSize);
+    return outBlock;
+}
+
+int
+RISCOS_VideoInit(_THIS)
+{
+    SDL_DisplayMode mode;
+    int *current_mode;
+    _kernel_swi_regs regs;
+    _kernel_oserror *error;
+
+    regs.r[0] = 1;
+    error = _kernel_swi(OS_ScreenMode, &regs, &regs);
+    if (error != NULL) {
+        SDL_SetError("Unable to retrieve the current screen mode: %s (%i)", error->errmess, error->errnum);
+        return -1;
+    }
+    current_mode = (int *)regs.r[1];
+
+    /* Use a fake 32-bpp desktop mode */
+    mode.w = current_mode[1];
+    mode.h = current_mode[2];
+    if ((current_mode[0] & 0x7F) == 1) {
+        mode.format = RISCOS_ModeToPixelFormat(current_mode);
+        mode.refresh_rate = current_mode[4];
+    } else if ((current_mode[0] & 0x7F) == 3) {
+        mode.format = RISCOS_ModeToPixelFormat(current_mode);
+        mode.refresh_rate = current_mode[6];
+    } else {
+        return -1;
+    }
+    mode.driverdata = copy_mode_block(current_mode);
+
+    if (SDL_AddBasicVideoDisplay(&mode) < 0) {
+        return -1;
+    }
+
+    SDL_AddDisplayMode(&_this->displays[0], &mode);
+
+    /* We're done! */
+    return 0;
+}
+
+static int
+RISCOS_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+    return 0;
+}
+
+void
+RISCOS_VideoQuit(_THIS)
+{
+}
+
+SDL_bool RISCOS_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info) {
+    if (info->version.major == SDL_MAJOR_VERSION &&
+        info->version.minor == SDL_MINOR_VERSION) {
+        info->subsystem = SDL_SYSWM_RISCOS;
+        return SDL_TRUE;
+    } else {
+        SDL_SetError("Application not compiled with SDL %d.%d",
+                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
+        return SDL_FALSE;
+    }
+}
+
+#endif /* SDL_VIDEO_DRIVER_RISCOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosvideo.h b/src/video/riscos/SDL_riscosvideo.h
new file mode 100644
index 0000000000..5bf4b144c4
--- /dev/null
+++ b/src/video/riscos/SDL_riscosvideo.h
@@ -0,0 +1,30 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_riscosvideo_h_
+#define SDL_riscosvideo_h_
+
+#include "../SDL_sysvideo.h"
+
+#endif /* SDL_riscosvideo_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */