diff --git a/VisualC/SDL/SDL_VS2012_WinRT.vcxproj b/VisualC/SDL/SDL_VS2012_WinRT.vcxproj
index 73d04e207..3bb971a7b 100644
--- a/VisualC/SDL/SDL_VS2012_WinRT.vcxproj
+++ b/VisualC/SDL/SDL_VS2012_WinRT.vcxproj
@@ -89,11 +89,11 @@
-
-
-
+
+
+
@@ -253,10 +253,10 @@
-
-
+
+
diff --git a/VisualC/tests/testthread/WinRT/Assets/Logo.png b/VisualC/tests/testthread/WinRT/Assets/Logo.png
new file mode 100644
index 000000000..e26771cb3
Binary files /dev/null and b/VisualC/tests/testthread/WinRT/Assets/Logo.png differ
diff --git a/VisualC/tests/testthread/WinRT/Assets/SmallLogo.png b/VisualC/tests/testthread/WinRT/Assets/SmallLogo.png
new file mode 100644
index 000000000..1eb0d9d52
Binary files /dev/null and b/VisualC/tests/testthread/WinRT/Assets/SmallLogo.png differ
diff --git a/VisualC/tests/testthread/WinRT/Assets/SplashScreen.png b/VisualC/tests/testthread/WinRT/Assets/SplashScreen.png
new file mode 100644
index 000000000..c951e031b
Binary files /dev/null and b/VisualC/tests/testthread/WinRT/Assets/SplashScreen.png differ
diff --git a/VisualC/tests/testthread/WinRT/Assets/StoreLogo.png b/VisualC/tests/testthread/WinRT/Assets/StoreLogo.png
new file mode 100644
index 000000000..dcb672712
Binary files /dev/null and b/VisualC/tests/testthread/WinRT/Assets/StoreLogo.png differ
diff --git a/VisualC/tests/testthread/WinRT/Package.appxmanifest b/VisualC/tests/testthread/WinRT/Package.appxmanifest
new file mode 100644
index 000000000..f02b3a173
--- /dev/null
+++ b/VisualC/tests/testthread/WinRT/Package.appxmanifest
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+ testthread_VS2012_WinRT
+ David
+ Assets\StoreLogo.png
+
+
+
+ 6.2.1
+ 6.2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VisualC/tests/testthread/WinRT/testthread_VS2012_WinRT.vcxproj b/VisualC/tests/testthread/WinRT/testthread_VS2012_WinRT.vcxproj
new file mode 100644
index 000000000..0f522e147
--- /dev/null
+++ b/VisualC/tests/testthread/WinRT/testthread_VS2012_WinRT.vcxproj
@@ -0,0 +1,159 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+ Debug
+ ARM
+
+
+ Release
+ ARM
+
+
+
+ {a8705bee-d01d-46a4-b2ab-feedfb5fdd11}
+ testthread_VS2012_WinRT
+ en-US
+ 11.0
+ true
+
+
+
+ Application
+ true
+ v110
+
+
+ Application
+ true
+ v110
+
+
+ Application
+ true
+ v110
+
+
+ Application
+ false
+ true
+ v110
+
+
+ Application
+ false
+ true
+ v110
+
+
+ Application
+ false
+ true
+ v110
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ testthread_VS2012_WinRT_TemporaryKey.pfx
+
+
+
+ d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies)
+
+
+ pch.h
+ $(IntDir)pch.pch
+ $(ProjectDir);$(IntermediateOutputPath);$(ProjectDir)..\..\..\..\include;%(AdditionalIncludeDirectories)
+ 4453
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ NotUsing
+ NotUsing
+ NotUsing
+ false
+ false
+ false
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ NotUsing
+ NotUsing
+ NotUsing
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+ {aeaea3a2-d4e6-45b1-8ec6-53d84287fc14}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VisualC/tests/testthread/WinRT/testthread_VS2012_WinRT_TemporaryKey.pfx b/VisualC/tests/testthread/WinRT/testthread_VS2012_WinRT_TemporaryKey.pfx
new file mode 100644
index 000000000..97fd1e190
Binary files /dev/null and b/VisualC/tests/testthread/WinRT/testthread_VS2012_WinRT_TemporaryKey.pfx differ
diff --git a/include/SDL_config_windowsrt.h b/include/SDL_config_windowsrt.h
index fb7fdb3b9..759dcb866 100644
--- a/include/SDL_config_windowsrt.h
+++ b/include/SDL_config_windowsrt.h
@@ -158,9 +158,9 @@ typedef unsigned int uintptr_t;
#define SDL_LOADSO_WINDOWS 1
/* Enable various threading systems */
-// TODO, WinRT: get threads working on WinRT
-#define SDL_THREADS_DISABLED 1
+//#define SDL_THREADS_DISABLED 1
//#define SDL_THREAD_WINDOWS 1
+#define SDL_THREAD_STDCPP 1
/* Enable various timer systems */
// TODO, WinRT: look into getting SDL's pre-WinRT timers working.
diff --git a/src/thread/SDL_thread_c.h b/src/thread/SDL_thread_c.h
index 565eb3d0e..eb2d6f68e 100644
--- a/src/thread/SDL_thread_c.h
+++ b/src/thread/SDL_thread_c.h
@@ -36,6 +36,8 @@
#include "windows/SDL_systhread_c.h"
#elif SDL_THREAD_NDS
#include "nds/SDL_systhread_c.h"
+#elif SDL_THREAD_STDCPP
+#include "stdcpp/SDL_systhread_c.h"
#else
#error Need thread implementation for this platform
#include "generic/SDL_systhread_c.h"
diff --git a/src/thread/stdcpp/SDL_syscond.c b/src/thread/stdcpp/SDL_syscond.c
new file mode 100644
index 000000000..7304badc1
--- /dev/null
+++ b/src/thread/stdcpp/SDL_syscond.c
@@ -0,0 +1,223 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ 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_config.h"
+
+/* An implementation of condition variables using semaphores and mutexes */
+/*
+ This implementation borrows heavily from the BeOS condition variable
+ implementation, written by Christopher Tate and Owen Smith. Thanks!
+ */
+
+#include "SDL_thread.h"
+
+struct SDL_cond
+{
+ SDL_mutex *lock;
+ int waiting;
+ int signals;
+ SDL_sem *wait_sem;
+ SDL_sem *wait_done;
+};
+
+/* Create a condition variable */
+SDL_cond *
+SDL_CreateCond(void)
+{
+ SDL_cond *cond;
+
+ cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
+ if (cond) {
+ cond->lock = SDL_CreateMutex();
+ cond->wait_sem = SDL_CreateSemaphore(0);
+ cond->wait_done = SDL_CreateSemaphore(0);
+ cond->waiting = cond->signals = 0;
+ if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
+ SDL_DestroyCond(cond);
+ cond = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return (cond);
+}
+
+/* Destroy a condition variable */
+void
+SDL_DestroyCond(SDL_cond * cond)
+{
+ if (cond) {
+ if (cond->wait_sem) {
+ SDL_DestroySemaphore(cond->wait_sem);
+ }
+ if (cond->wait_done) {
+ SDL_DestroySemaphore(cond->wait_done);
+ }
+ if (cond->lock) {
+ SDL_DestroyMutex(cond->lock);
+ }
+ SDL_free(cond);
+ }
+}
+
+/* Restart one of the threads that are waiting on the condition variable */
+int
+SDL_CondSignal(SDL_cond * cond)
+{
+ if (!cond) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->waiting > cond->signals) {
+ ++cond->signals;
+ SDL_SemPost(cond->wait_sem);
+ SDL_UnlockMutex(cond->lock);
+ SDL_SemWait(cond->wait_done);
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Restart all threads that are waiting on the condition variable */
+int
+SDL_CondBroadcast(SDL_cond * cond)
+{
+ if (!cond) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->waiting > cond->signals) {
+ int i, num_waiting;
+
+ num_waiting = (cond->waiting - cond->signals);
+ cond->signals = cond->waiting;
+ for (i = 0; i < num_waiting; ++i) {
+ SDL_SemPost(cond->wait_sem);
+ }
+ /* Now all released threads are blocked here, waiting for us.
+ Collect them all (and win fabulous prizes!) :-)
+ */
+ SDL_UnlockMutex(cond->lock);
+ for (i = 0; i < num_waiting; ++i) {
+ SDL_SemWait(cond->wait_done);
+ }
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Wait on the condition variable for at most 'ms' milliseconds.
+ The mutex must be locked before entering this function!
+ The mutex is unlocked during the wait, and locked again after the wait.
+
+Typical use:
+
+Thread A:
+ SDL_LockMutex(lock);
+ while ( ! condition ) {
+ SDL_CondWait(cond, lock);
+ }
+ SDL_UnlockMutex(lock);
+
+Thread B:
+ SDL_LockMutex(lock);
+ ...
+ condition = true;
+ ...
+ SDL_CondSignal(cond);
+ SDL_UnlockMutex(lock);
+ */
+int
+SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
+{
+ int retval;
+
+ if (!cond) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ /* Obtain the protection mutex, and increment the number of waiters.
+ This allows the signal mechanism to only perform a signal if there
+ are waiting threads.
+ */
+ SDL_LockMutex(cond->lock);
+ ++cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Unlock the mutex, as is required by condition variable semantics */
+ SDL_UnlockMutex(mutex);
+
+ /* Wait for a signal */
+ if (ms == SDL_MUTEX_MAXWAIT) {
+ retval = SDL_SemWait(cond->wait_sem);
+ } else {
+ retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
+ }
+
+ /* Let the signaler know we have completed the wait, otherwise
+ the signaler can race ahead and get the condition semaphore
+ if we are stopped between the mutex unlock and semaphore wait,
+ giving a deadlock. See the following URL for details:
+ http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->signals > 0) {
+ /* If we timed out, we need to eat a condition signal */
+ if (retval > 0) {
+ SDL_SemWait(cond->wait_sem);
+ }
+ /* We always notify the signal thread that we are done */
+ SDL_SemPost(cond->wait_done);
+
+ /* Signal handshake complete */
+ --cond->signals;
+ }
+ --cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Lock the mutex, as is required by condition variable semantics */
+ SDL_LockMutex(mutex);
+
+ return retval;
+}
+
+/* Wait on the condition variable forever */
+int
+SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
+{
+ return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/stdcpp/SDL_sysmutex.c b/src/thread/stdcpp/SDL_sysmutex.c
new file mode 100644
index 000000000..1a6b2715c
--- /dev/null
+++ b/src/thread/stdcpp/SDL_sysmutex.c
@@ -0,0 +1,135 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ 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_config.h"
+
+/* An implementation of mutexes using semaphores */
+
+#include "SDL_thread.h"
+#include "SDL_systhread_c.h"
+
+
+struct SDL_mutex
+{
+ int recursive;
+ SDL_threadID owner;
+ SDL_sem *sem;
+};
+
+/* Create a mutex */
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+ SDL_mutex *mutex;
+
+ /* Allocate mutex memory */
+ mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
+ if (mutex) {
+ /* Create the mutex semaphore, with initial value 1 */
+ mutex->sem = SDL_CreateSemaphore(1);
+ mutex->recursive = 0;
+ mutex->owner = 0;
+ if (!mutex->sem) {
+ SDL_free(mutex);
+ mutex = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return mutex;
+}
+
+/* Free the mutex */
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+ if (mutex) {
+ if (mutex->sem) {
+ SDL_DestroySemaphore(mutex->sem);
+ }
+ SDL_free(mutex);
+ }
+}
+
+/* Lock the semaphore */
+int
+SDL_mutexP(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+ return 0;
+#else
+ SDL_threadID this_thread;
+
+ if (mutex == NULL) {
+ SDL_SetError("Passed a NULL mutex");
+ return -1;
+ }
+
+ this_thread = SDL_ThreadID();
+ if (mutex->owner == this_thread) {
+ ++mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ We set the locking thread id after we obtain the lock
+ so unlocks from other threads will fail.
+ */
+ SDL_SemWait(mutex->sem);
+ mutex->owner = this_thread;
+ mutex->recursive = 0;
+ }
+
+ return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* Unlock the mutex */
+int
+SDL_mutexV(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+ return 0;
+#else
+ if (mutex == NULL) {
+ SDL_SetError("Passed a NULL mutex");
+ return -1;
+ }
+
+ /* If we don't own the mutex, we can't unlock it */
+ if (SDL_ThreadID() != mutex->owner) {
+ SDL_SetError("mutex not owned by this thread");
+ return -1;
+ }
+
+ if (mutex->recursive) {
+ --mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ First reset the owner so another thread doesn't lock
+ the mutex and set the ownership before we reset it,
+ then release the lock semaphore.
+ */
+ mutex->owner = 0;
+ SDL_SemPost(mutex->sem);
+ }
+ return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/stdcpp/SDL_sysmutex_c.h b/src/thread/stdcpp/SDL_sysmutex_c.h
new file mode 100644
index 000000000..ed546b689
--- /dev/null
+++ b/src/thread/stdcpp/SDL_sysmutex_c.h
@@ -0,0 +1,22 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ 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_config.h"
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/stdcpp/SDL_systhread.c b/src/thread/stdcpp/SDL_systhread.c
new file mode 100644
index 000000000..ed557a461
--- /dev/null
+++ b/src/thread/stdcpp/SDL_systhread.c
@@ -0,0 +1,59 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ 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_config.h"
+
+/* Thread management routines for SDL */
+
+#include "SDL_thread.h"
+#include "../SDL_systhread.h"
+
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
+{
+ SDL_SetError("Threads are not supported on this platform");
+ return (-1);
+}
+
+void
+SDL_SYS_SetupThread(const char *name)
+{
+ return;
+}
+
+SDL_threadID
+SDL_ThreadID(void)
+{
+ return (0);
+}
+
+int
+SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{
+ return (0);
+}
+
+void
+SDL_SYS_WaitThread(SDL_Thread * thread)
+{
+ return;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/stdcpp/SDL_systhread_c.h b/src/thread/stdcpp/SDL_systhread_c.h
new file mode 100644
index 000000000..4a060c98a
--- /dev/null
+++ b/src/thread/stdcpp/SDL_systhread_c.h
@@ -0,0 +1,26 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ 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_config.h"
+
+/* For a thread handle, use a void pointer to a std::thread */
+typedef void * SYS_ThreadHandle;
+
+/* vi: set ts=4 sw=4 expandtab: */