diff --git a/recipes/mgba/01_redox.patch b/recipes/mgba/01_redox.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0ba8702d137df6695e515872390978e94b948905
--- /dev/null
+++ b/recipes/mgba/01_redox.patch
@@ -0,0 +1,138 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index fa01e3a5..5910934a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -1,4 +1,4 @@
+-cmake_minimum_required(VERSION 3.1)
++cmake_minimum_required(VERSION 3.4)
+ if(POLICY CMP0025)
+ 	cmake_policy(SET CMP0025 NEW)
+ endif()
+@@ -241,8 +241,8 @@ elseif(UNIX)
+ 		add_definitions(-D_GNU_SOURCE)
+ 	endif()
+ 	if(NOT APPLE AND NOT HAIKU)
+-		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
+-		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
++		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lpthread")
++		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lpthread")
+ 	endif()
+ 
+ 	list(APPEND CORE_VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-dirent.c)
+diff --git a/include/mgba-util/platform/posix/threading.h b/include/mgba-util/platform/posix/threading.h
+index 468e1460..50cba731 100644
+--- a/include/mgba-util/platform/posix/threading.h
++++ b/include/mgba-util/platform/posix/threading.h
+@@ -85,25 +85,8 @@ static inline int ThreadJoin(Thread thread) {
+ }
+ 
+ static inline int ThreadSetName(const char* name) {
+-#ifdef __APPLE__
+-#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060
+-	return pthread_setname_np(name);
+-#else
+ 	UNUSED(name);
+ 	return 0;
+-#endif
+-#elif defined(__FreeBSD__) || defined(__OpenBSD__)
+-	pthread_set_name_np(pthread_self(), name);
+-	return 0;
+-#elif defined(__HAIKU__)
+-	rename_thread(find_thread(NULL), name);
+-	return 0;
+-#elif !defined(BUILD_PANDORA) // Pandora's glibc is too old
+-	return pthread_setname_np(pthread_self(), name);
+-#else
+-	UNUSED(name);
+-	return 0;
+-#endif
+ }
+ 
+ CXX_GUARD_END
+diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h
+index e5c9dde1..82d3b828 100644
+--- a/include/mgba/core/interface.h
++++ b/include/mgba/core/interface.h
+@@ -31,7 +31,7 @@ typedef uint32_t color_t;
+ #define M_G8(X) (((((X) >> 2) & 0xF8) * 0x21) >> 5)
+ #define M_B8(X) (((((X) >> 7) & 0xF8) * 0x21) >> 5)
+ 
+-#define M_RGB5_TO_BGR8(X) ((M_R5(X) << 3) | (M_G5(X) << 11) | (M_B5(X) << 19))
++#define M_RGB5_TO_BGR8(X) ((M_B5(X) << 3) | (M_G5(X) << 11) | (M_R5(X) << 19))
+ #define M_RGB8_TO_BGR5(X) ((((X) & 0xF8) >> 3) | (((X) & 0xF800) >> 6) | (((X) & 0xF80000) >> 9))
+ #define M_RGB8_TO_RGB5(X) ((((X) & 0xF8) << 7) | (((X) & 0xF800) >> 6) | (((X) & 0xF80000) >> 19))
+ 
+diff --git a/src/platform/sdl/sdl-audio.c b/src/platform/sdl/sdl-audio.c
+index ab0bd830..7cd77495 100644
+--- a/src/platform/sdl/sdl-audio.c
++++ b/src/platform/sdl/sdl-audio.c
+@@ -24,6 +24,15 @@ bool mSDLInitAudio(struct mSDLAudio* context, struct mCoreThread* threadContext)
+ 		return false;
+ 	}
+ 
++	// Workaround: The thread of _mSDLAudioCallback cannot see these changes
++	// unless they are made before the SDL_OpenAudio call.
++	// This makes the `if (!context || !audioContext->core) {` check in
++	// _mSDLAudioCallback not bail out. This is rather important, the whole
++	// emulation seems to be synched to the audio.
++	context->core = threadContext->core;
++	context->sync = &threadContext->impl->sync;
++	// --
++
+ 	context->desiredSpec.freq = context->sampleRate;
+ 	context->desiredSpec.format = AUDIO_S16SYS;
+ 	context->desiredSpec.channels = 2;
+diff --git a/src/third-party/zlib/contrib/minizip/ioapi.c b/src/third-party/zlib/contrib/minizip/ioapi.c
+index 7f5c191b..744dd96b 100644
+--- a/src/third-party/zlib/contrib/minizip/ioapi.c
++++ b/src/third-party/zlib/contrib/minizip/ioapi.c
+@@ -14,7 +14,7 @@
+         #define _CRT_SECURE_NO_WARNINGS
+ #endif
+ 
+-#if defined(__APPLE__) || defined(IOAPI_NO_64)
++#if defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__redox__)
+ // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+ #define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+ #define FTELLO_FUNC(stream) ftello(stream)
+diff --git a/src/util/vfs/vfs-fd.c b/src/util/vfs/vfs-fd.c
+index 4a20eaf7..3307709c 100644
+--- a/src/util/vfs/vfs-fd.c
++++ b/src/util/vfs/vfs-fd.c
+@@ -42,7 +42,8 @@ struct VFile* VFileOpenFD(const char* path, int flags) {
+ 	MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof(wpath) / sizeof(*wpath));
+ 	int fd = _wopen(wpath, flags, 0666);
+ #else
+-	int fd = open(path, flags, 0666);
++	// Workaround for the _vfdMap permission problems below
++	int fd = open(path, flags | O_RDWR, 0666);
+ #endif
+ 	return VFileFromFD(fd);
+ }
+@@ -164,24 +165,6 @@ static ssize_t _vfdSize(struct VFile* vf) {
+ static bool _vfdSync(struct VFile* vf, const void* buffer, size_t size) {
+ 	UNUSED(buffer);
+ 	UNUSED(size);
+-	struct VFileFD* vfd = (struct VFileFD*) vf;
+-#ifndef _WIN32
+-#ifdef __HAIKU__
+-	futimens(vfd->fd, NULL);
+-#else
+-	futimes(vfd->fd, NULL);
+-#endif
+-	if (buffer && size) {
+-		return msync(buffer, size, MS_SYNC) == 0;
+-	}
+-	return fsync(vfd->fd) == 0;
+-#else
+-	HANDLE h = (HANDLE) _get_osfhandle(vfd->fd);
+-	FILETIME ft;
+-	SYSTEMTIME st;
+-	GetSystemTime(&st);
+-	SystemTimeToFileTime(&st, &ft);
+-	SetFileTime(h, NULL, &ft, &ft);
+-	return FlushFileBuffers(h);
+-#endif
++	printf("_vfdSync\n");
++	return true;
+ }
diff --git a/recipes/mgba/recipe.sh b/recipes/mgba/recipe.sh
new file mode 100644
index 0000000000000000000000000000000000000000..57484eccce94b98d034e9580695d7fd4557a387b
--- /dev/null
+++ b/recipes/mgba/recipe.sh
@@ -0,0 +1,53 @@
+VERSION=0.7
+GIT=https://github.com/mgba-emu/mgba.git
+BRANCH=$VERSION
+BUILD_DEPENDS=(sdl liborbital libiconv pixman)
+
+function recipe_version {
+    echo "$VERSION"
+    skip=1
+}
+
+function recipe_update {
+    echo "skipping update"
+    skip=1
+}
+
+function recipe_build {
+    sysroot="$(realpath ../sysroot)"
+    export CFLAGS="-I$sysroot/include -I$sysroot/include/SDL"
+    export LDFLAGS="-L$sysroot/lib"
+
+    mkdir -p build
+    cd build
+    cmake \
+        -DCMAKE_INSTALL_PREFIX:PATH=/ \
+        -DBUILD_STATIC=ON \
+        -DBUILD_SHARED=OFF \
+        -DBUILD_QT=OFF \
+        -DUSE_SQLITE3=OFF \
+        -DUSE_DEBUGGERS=OFF \
+        -DBUILD_SDL=ON \
+        -DSDL_VERSION="1.2" \
+        -DSDL_LIBRARY="-lSDL -lorbital" \
+        ..
+    VERBOSE=1 make all -j"$(nproc)"
+    skip=1
+}
+
+function recipe_test {
+    echo "skipping test"
+    skip=1
+}
+
+function recipe_clean {
+    make clean
+    skip=1
+}
+
+function recipe_stage {
+    dest="$(realpath $1)"
+    mkdir -pv "$dest/bin"
+    cp "../build/build/sdl/mgba" "$dest/bin/mgba"
+    skip=1
+}