diff --git a/CMakeLists.txt b/CMakeLists.txt
index a7f342579d..a40bc609a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1480,8 +1480,6 @@ elseif(EMSCRIPTEN)
# project. Uncomment at will for verbose cross-compiling -I/../ path info.
sdl_compile_options(PRIVATE "-Wno-warn-absolute-paths")
- sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/emscripten/*.c")
-
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/emscripten/*.c")
set(HAVE_SDL_MAIN_CALLBACKS TRUE)
@@ -1866,12 +1864,14 @@ elseif(WINDOWS)
int main(int argc, char **argv) { return 0; }" HAVE_WIN32_CC)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/windows/*.c")
+ sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/windows/*.c")
if(WINDOWS_STORE)
enable_language(CXX)
sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/core/winrt/*.c"
"${SDL3_SOURCE_DIR}/src/core/winrt/*.cpp"
+ "${SDL3_SOURCE_DIR}/src/main/winrt/*.cpp"
)
endif()
@@ -2727,7 +2727,7 @@ elseif(VITA)
sdl_compile_definitions(PRIVATE "__VITA__")
elseif(PSP)
- sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/psp/*.c")
+ sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/psp/*.c")
if(SDL_AUDIO)
set(SDL_AUDIO_DRIVER_PSP 1)
@@ -2796,7 +2796,7 @@ elseif(PS2)
sdl_compile_definitions(PRIVATE "PS2" "__PS2__")
sdl_include_directories(PRIVATE SYSTEM "$ENV{PS2SDK}/ports/include" "$ENV{PS2DEV}/gsKit/include")
- sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/ps2/*.c")
+ sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/ps2/*.c")
if(SDL_AUDIO)
set(SDL_AUDIO_DRIVER_PS2 1)
@@ -2853,7 +2853,7 @@ elseif(PS2)
ps2_drivers
)
elseif(N3DS)
- sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/n3ds/*.c")
+ sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/n3ds/*.c")
if(SDL_AUDIO)
set(SDL_AUDIO_DRIVER_N3DS 1)
diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index bb7c85405b..67e74896cd 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -503,8 +503,10 @@
+
+
@@ -600,7 +602,6 @@
-
diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters
index 2b4f69eb03..478d401f0c 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj.filters
+++ b/VisualC-GDK/SDL/SDL.vcxproj.filters
@@ -18,6 +18,8 @@
+
+
@@ -35,7 +37,6 @@
-
diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj
index 0231e2dd03..072c133d31 100644
--- a/VisualC-WinRT/SDL-UWP.vcxproj
+++ b/VisualC-WinRT/SDL-UWP.vcxproj
@@ -268,7 +268,6 @@
-
@@ -359,8 +358,20 @@
+
+
+ true
+ $(IntDir)$(TargetName)_cpp.pch
+ $(IntDir)$(TargetName)_cpp.pch
+ $(IntDir)$(TargetName)_cpp.pch
+ $(IntDir)$(TargetName)_cpp.pch
+ $(IntDir)$(TargetName)_cpp.pch
+ $(IntDir)$(TargetName)_cpp.pch
+ $(IntDir)$(TargetName)_cpp.pch
+ $(IntDir)$(TargetName)_cpp.pch
+
true
diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters
index 7112f2f9cc..4e573d6f28 100644
--- a/VisualC-WinRT/SDL-UWP.vcxproj.filters
+++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters
@@ -34,6 +34,9 @@
{0000c99bfadbbcb05a474a8472910000}
+
+ {00006680a11742e2b280c6453be80000}
+
@@ -549,9 +552,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -660,6 +660,12 @@
main
+
+ Source Files
+
+
+ main\winrt
+
Source Files
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index 87dd7ee8ee..879c607e8d 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -404,6 +404,8 @@
+
+
@@ -506,7 +508,6 @@
-
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index 4eb44ad41f..93db4f1994 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -202,6 +202,9 @@
{748cf015-00b8-4e71-ac48-02e947e4d93d}
+
+ {00009d5ded166cc6c6680ec771a30000}
+
@@ -919,6 +922,12 @@
main
+
+ main
+
+
+ main\windows
+
@@ -961,9 +970,6 @@
core
-
- core
-
core\windows
diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
index aace663af0..f13182b501 100644
--- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -1145,6 +1145,7 @@
00008B5A0CB83D2069E80000 /* ios */,
00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */,
00003260407E1002EAC10000 /* SDL_main_callbacks.h */,
+ F36C7AD0294BA009004D61C3 /* SDL_runapp.c */,
);
path = main;
sourceTree = "";
@@ -2255,7 +2256,6 @@
isa = PBXGroup;
children = (
E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */,
- F36C7AD0294BA009004D61C3 /* SDL_runapp.c */,
);
path = core;
sourceTree = "";
diff --git a/src/core/gdk/SDL_gdk.cpp b/src/core/gdk/SDL_gdk.cpp
index 8e7a8caaa4..80166bae3c 100644
--- a/src/core/gdk/SDL_gdk.cpp
+++ b/src/core/gdk/SDL_gdk.cpp
@@ -26,7 +26,6 @@ extern "C" {
}
#include
#include
-#include /* CommandLineToArgvW() */
#include
static XTaskQueueHandle GDK_GlobalTaskQueue;
@@ -74,162 +73,6 @@ void GDK_DispatchTaskQueue(void)
}
}
-/* Pop up an out of memory message, returns to Windows */
-static BOOL OutOfMemory(void)
-{
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
- return FALSE;
-}
-
-/* Gets the arguments with GetCommandLine, converts them to argc and argv
- and calls SDL_main */
-extern "C"
-int SDL_RunApp(int, char**, SDL_main_func mainFunction, void *reserved)
-{
- LPWSTR *argvw;
- char **argv;
- int i, argc, result;
- HRESULT hr;
- XTaskQueueHandle taskQueue;
-
- argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
- if (argvw == NULL) {
- return OutOfMemory();
- }
-
- /* Note that we need to be careful about how we allocate/free memory here.
- * If the application calls SDL_SetMemoryFunctions(), we can't rely on
- * SDL_free() to use the same allocator after SDL_main() returns.
- */
-
- /* Parse it into argv and argc */
- argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv));
- if (argv == NULL) {
- return OutOfMemory();
- }
- for (i = 0; i < argc; ++i) {
- const int utf8size = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
- if (!utf8size) { // uhoh?
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
- return -1;
- }
-
- argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, utf8size); // this size includes the null-terminator character.
- if (!argv[i]) {
- return OutOfMemory();
- }
-
- if (WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argv[i], utf8size, NULL, NULL) == 0) { // failed? uhoh!
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
- return -1;
- }
- }
- argv[i] = NULL;
- LocalFree(argvw);
-
- hr = XGameRuntimeInitialize();
-
- if (SUCCEEDED(hr) && SDL_GDKGetTaskQueue(&taskQueue) == 0) {
- Uint32 titleid = 0;
- char scidBuffer[64];
- XblInitArgs xblArgs;
-
- XTaskQueueSetCurrentProcessTaskQueue(taskQueue);
-
- /* Try to get the title ID and initialize Xbox Live */
- hr = XGameGetXboxTitleId(&titleid);
- if (SUCCEEDED(hr)) {
- SDL_zero(xblArgs);
- xblArgs.queue = taskQueue;
- SDL_snprintf(scidBuffer, 64, "00000000-0000-0000-0000-0000%08X", titleid);
- xblArgs.scid = scidBuffer;
- hr = XblInitialize(&xblArgs);
- } else {
- SDL_SetError("[GDK] Unable to get titleid. Will not call XblInitialize. Check MicrosoftGame.config!");
- }
-
- SDL_SetMainReady();
-
- /* Register suspend/resume handling */
- plmSuspendComplete = CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
- if (!plmSuspendComplete) {
- SDL_SetError("[GDK] Unable to create plmSuspendComplete event");
- return -1;
- }
- auto rascn = [](BOOLEAN quiesced, PVOID context) {
- SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler");
- if (quiesced) {
- ResetEvent(plmSuspendComplete);
- SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND);
-
- // To defer suspension, we must wait to exit this callback.
- // IMPORTANT: The app must call SDL_GDKSuspendComplete() to release this lock.
- (void)WaitForSingleObject(plmSuspendComplete, INFINITE);
-
- SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler: plmSuspendComplete event signaled.");
- } else {
- SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
- }
- };
- if (RegisterAppStateChangeNotification(rascn, NULL, &hPLM)) {
- SDL_SetError("[GDK] Unable to call RegisterAppStateChangeNotification");
- return -1;
- }
-
- /* Register constrain/unconstrain handling */
- auto raccn = [](BOOLEAN constrained, PVOID context) {
- SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler");
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (_this) {
- if (constrained) {
- SDL_SetKeyboardFocus(NULL);
- } else {
- SDL_SetKeyboardFocus(_this->windows);
- }
- }
- };
- if (RegisterAppConstrainedChangeNotification(raccn, NULL, &hCPLM)) {
- SDL_SetError("[GDK] Unable to call RegisterAppConstrainedChangeNotification");
- return -1;
- }
-
- /* Run the application main() code */
- result = mainFunction(argc, argv);
-
- /* Unregister suspend/resume handling */
- UnregisterAppStateChangeNotification(hPLM);
- CloseHandle(plmSuspendComplete);
-
- /* Unregister constrain/unconstrain handling */
- UnregisterAppConstrainedChangeNotification(hCPLM);
-
- /* !!! FIXME: This follows the docs exactly, but for some reason still leaks handles on exit? */
- /* Terminate the task queue and dispatch any pending tasks */
- XTaskQueueTerminate(taskQueue, false, nullptr, nullptr);
- while (XTaskQueueDispatch(taskQueue, XTaskQueuePort::Completion, 0))
- ;
-
- XTaskQueueCloseHandle(taskQueue);
-
- XGameRuntimeUninitialize();
- } else {
-#ifdef SDL_PLATFORM_WINGDK
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "[GDK] Could not initialize - aborting", NULL);
-#else
- SDL_assert_always(0 && "[GDK] Could not initialize - aborting");
-#endif
- result = -1;
- }
-
- /* Free argv, to avoid memory leak */
- for (i = 0; i < argc; ++i) {
- HeapFree(GetProcessHeap(), 0, argv[i]);
- }
- HeapFree(GetProcessHeap(), 0, argv);
-
- return result;
-}
-
extern "C"
void SDL_GDKSuspendComplete()
{
diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c
index eea88ff8e6..961d4de801 100644
--- a/src/core/windows/SDL_windows.c
+++ b/src/core/windows/SDL_windows.c
@@ -389,81 +389,4 @@ int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr,
return WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
}
-
-/* Win32-specific SDL_RunApp(), which does most of the SDL_main work,
- based on SDL_windows_main.c, placed in the public domain by Sam Lantinga 4/13/98 */
-#ifdef SDL_PLATFORM_WIN32
-
-#include /* CommandLineToArgvW() */
-
-/* Pop up an out of memory message, returns to Windows */
-static int OutOfMemory(void)
-{
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
- return -1;
-}
-
-int MINGW32_FORCEALIGN SDL_RunApp(int _argc, char* _argv[], SDL_main_func mainFunction, void * reserved)
-{
-
- /* Gets the arguments with GetCommandLine, converts them to argc and argv
- and calls SDL_main */
-
- LPWSTR *argvw;
- char **argv;
- int i, argc, result;
-
- (void)_argc; (void)_argv; (void)reserved;
-
- argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
- if (!argvw) {
- return OutOfMemory();
- }
-
- /* Note that we need to be careful about how we allocate/free memory here.
- * If the application calls SDL_SetMemoryFunctions(), we can't rely on
- * SDL_free() to use the same allocator after SDL_main() returns.
- */
-
- /* Parse it into argv and argc */
- argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv));
- if (!argv) {
- return OutOfMemory();
- }
- for (i = 0; i < argc; ++i) {
- const int utf8size = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
- if (!utf8size) { // uhoh?
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
- return -1;
- }
-
- argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, utf8size); // this size includes the null-terminator character.
- if (!argv[i]) {
- return OutOfMemory();
- }
-
- if (WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argv[i], utf8size, NULL, NULL) == 0) { // failed? uhoh!
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
- return -1;
- }
- }
- argv[i] = NULL;
- LocalFree(argvw);
-
- SDL_SetMainReady();
-
- /* Run the application main() code */
- result = mainFunction(argc, argv);
-
- /* Free argv, to avoid memory leak */
- for (i = 0; i < argc; ++i) {
- HeapFree(GetProcessHeap(), 0, argv[i]);
- }
- HeapFree(GetProcessHeap(), 0, argv);
-
- return result;
-}
-
-#endif /* SDL_PLATFORM_WIN32 */
-
#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) */
diff --git a/src/core/winrt/SDL_winrtapp_common.cpp b/src/core/winrt/SDL_winrtapp_common.cpp
index 9df3c1d888..6cdb71d530 100644
--- a/src/core/winrt/SDL_winrtapp_common.cpp
+++ b/src/core/winrt/SDL_winrtapp_common.cpp
@@ -20,26 +20,10 @@
*/
#include "SDL_internal.h"
-#include "SDL_winrtapp_direct3d.h"
-#include "SDL_winrtapp_xaml.h"
-
#include
int (*WINRT_SDLAppEntryPoint)(int, char **) = NULL;
-extern "C"
-int SDL_RunApp(int, char**, SDL_main_func mainFunction, void * xamlBackgroundPanel)
-{
- if (xamlBackgroundPanel) {
- return SDL_WinRTInitXAMLApp(mainFunction, xamlBackgroundPanel);
- } else {
- if (FAILED(Windows::Foundation::Initialize(RO_INIT_MULTITHREADED))) {
- return 1;
- }
- return SDL_WinRTInitNonXAMLApp(mainFunction);
- }
-}
-
extern "C"
SDL_WinRT_DeviceFamily SDL_WinRTGetDeviceFamily()
{
diff --git a/src/core/SDL_runapp.c b/src/main/SDL_runapp.c
similarity index 100%
rename from src/core/SDL_runapp.c
rename to src/main/SDL_runapp.c
diff --git a/src/core/emscripten/SDL_emscripten.c b/src/main/emscripten/SDL_sysmain_runapp.c
similarity index 100%
rename from src/core/emscripten/SDL_emscripten.c
rename to src/main/emscripten/SDL_sysmain_runapp.c
diff --git a/src/main/gdk/SDL_sysmain_runapp.cpp b/src/main/gdk/SDL_sysmain_runapp.cpp
new file mode 100644
index 0000000000..4517b28577
--- /dev/null
+++ b/src/main/gdk/SDL_sysmain_runapp.cpp
@@ -0,0 +1,187 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 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_internal.h"
+
+extern "C" {
+#include "../../core/windows/SDL_windows.h"
+#include "../../events/SDL_events_c.h"
+}
+#include
+#include
+#include /* CommandLineToArgvW() */
+#include
+
+/* Pop up an out of memory message, returns to Windows */
+static BOOL OutOfMemory(void)
+{
+ SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
+ return FALSE;
+}
+
+/* Gets the arguments with GetCommandLine, converts them to argc and argv
+ and calls SDL_main */
+extern "C"
+int SDL_RunApp(int, char**, SDL_main_func mainFunction, void *reserved)
+{
+ LPWSTR *argvw;
+ char **argv;
+ int i, argc, result;
+ HRESULT hr;
+ XTaskQueueHandle taskQueue;
+
+ argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (argvw == NULL) {
+ return OutOfMemory();
+ }
+
+ /* Note that we need to be careful about how we allocate/free memory here.
+ * If the application calls SDL_SetMemoryFunctions(), we can't rely on
+ * SDL_free() to use the same allocator after SDL_main() returns.
+ */
+
+ /* Parse it into argv and argc */
+ argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv));
+ if (argv == NULL) {
+ return OutOfMemory();
+ }
+ for (i = 0; i < argc; ++i) {
+ const int utf8size = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
+ if (!utf8size) { // uhoh?
+ SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+ return -1;
+ }
+
+ argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, utf8size); // this size includes the null-terminator character.
+ if (!argv[i]) {
+ return OutOfMemory();
+ }
+
+ if (WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argv[i], utf8size, NULL, NULL) == 0) { // failed? uhoh!
+ SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+ return -1;
+ }
+ }
+ argv[i] = NULL;
+ LocalFree(argvw);
+
+ hr = XGameRuntimeInitialize();
+
+ if (SUCCEEDED(hr) && SDL_GDKGetTaskQueue(&taskQueue) == 0) {
+ Uint32 titleid = 0;
+ char scidBuffer[64];
+ XblInitArgs xblArgs;
+
+ XTaskQueueSetCurrentProcessTaskQueue(taskQueue);
+
+ /* Try to get the title ID and initialize Xbox Live */
+ hr = XGameGetXboxTitleId(&titleid);
+ if (SUCCEEDED(hr)) {
+ SDL_zero(xblArgs);
+ xblArgs.queue = taskQueue;
+ SDL_snprintf(scidBuffer, 64, "00000000-0000-0000-0000-0000%08X", titleid);
+ xblArgs.scid = scidBuffer;
+ hr = XblInitialize(&xblArgs);
+ } else {
+ SDL_SetError("[GDK] Unable to get titleid. Will not call XblInitialize. Check MicrosoftGame.config!");
+ }
+
+ SDL_SetMainReady();
+
+ /* Register suspend/resume handling */
+ plmSuspendComplete = CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
+ if (!plmSuspendComplete) {
+ SDL_SetError("[GDK] Unable to create plmSuspendComplete event");
+ return -1;
+ }
+ auto rascn = [](BOOLEAN quiesced, PVOID context) {
+ SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler");
+ if (quiesced) {
+ ResetEvent(plmSuspendComplete);
+ SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND);
+
+ // To defer suspension, we must wait to exit this callback.
+ // IMPORTANT: The app must call SDL_GDKSuspendComplete() to release this lock.
+ (void)WaitForSingleObject(plmSuspendComplete, INFINITE);
+
+ SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler: plmSuspendComplete event signaled.");
+ } else {
+ SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
+ }
+ };
+ if (RegisterAppStateChangeNotification(rascn, NULL, &hPLM)) {
+ SDL_SetError("[GDK] Unable to call RegisterAppStateChangeNotification");
+ return -1;
+ }
+
+ /* Register constrain/unconstrain handling */
+ auto raccn = [](BOOLEAN constrained, PVOID context) {
+ SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler");
+ SDL_VideoDevice *_this = SDL_GetVideoDevice();
+ if (_this) {
+ if (constrained) {
+ SDL_SetKeyboardFocus(NULL);
+ } else {
+ SDL_SetKeyboardFocus(_this->windows);
+ }
+ }
+ };
+ if (RegisterAppConstrainedChangeNotification(raccn, NULL, &hCPLM)) {
+ SDL_SetError("[GDK] Unable to call RegisterAppConstrainedChangeNotification");
+ return -1;
+ }
+
+ /* Run the application main() code */
+ result = mainFunction(argc, argv);
+
+ /* Unregister suspend/resume handling */
+ UnregisterAppStateChangeNotification(hPLM);
+ CloseHandle(plmSuspendComplete);
+
+ /* Unregister constrain/unconstrain handling */
+ UnregisterAppConstrainedChangeNotification(hCPLM);
+
+ /* !!! FIXME: This follows the docs exactly, but for some reason still leaks handles on exit? */
+ /* Terminate the task queue and dispatch any pending tasks */
+ XTaskQueueTerminate(taskQueue, false, nullptr, nullptr);
+ while (XTaskQueueDispatch(taskQueue, XTaskQueuePort::Completion, 0))
+ ;
+
+ XTaskQueueCloseHandle(taskQueue);
+
+ XGameRuntimeUninitialize();
+ } else {
+#ifdef SDL_PLATFORM_WINGDK
+ SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "[GDK] Could not initialize - aborting", NULL);
+#else
+ SDL_assert_always(0 && "[GDK] Could not initialize - aborting");
+#endif
+ result = -1;
+ }
+
+ /* Free argv, to avoid memory leak */
+ for (i = 0; i < argc; ++i) {
+ HeapFree(GetProcessHeap(), 0, argv[i]);
+ }
+ HeapFree(GetProcessHeap(), 0, argv);
+
+ return result;
+}
+
diff --git a/src/core/n3ds/SDL_n3ds.c b/src/main/n3ds/SDL_sysmain_runapp.c
similarity index 100%
rename from src/core/n3ds/SDL_n3ds.c
rename to src/main/n3ds/SDL_sysmain_runapp.c
diff --git a/src/core/ngage/SDL_ngage_runapp.cpp b/src/main/ngage/SDL_sysmain_runapp.cpp
similarity index 100%
rename from src/core/ngage/SDL_ngage_runapp.cpp
rename to src/main/ngage/SDL_sysmain_runapp.cpp
diff --git a/src/core/ps2/SDL_ps2.c b/src/main/ps2/SDL_sysmain_runapp.c
similarity index 100%
rename from src/core/ps2/SDL_ps2.c
rename to src/main/ps2/SDL_sysmain_runapp.c
diff --git a/src/core/psp/SDL_psp.c b/src/main/psp/SDL_sysmain_runapp.c
similarity index 100%
rename from src/core/psp/SDL_psp.c
rename to src/main/psp/SDL_sysmain_runapp.c
diff --git a/src/main/windows/SDL_sysmain_runapp.c b/src/main/windows/SDL_sysmain_runapp.c
new file mode 100644
index 0000000000..426564e0cc
--- /dev/null
+++ b/src/main/windows/SDL_sysmain_runapp.c
@@ -0,0 +1,99 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 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_internal.h"
+
+#ifdef SDL_PLATFORM_WIN32
+
+#include "../../core/windows/SDL_windows.h"
+
+/* Win32-specific SDL_RunApp(), which does most of the SDL_main work,
+ based on SDL_windows_main.c, placed in the public domain by Sam Lantinga 4/13/98 */
+
+#include /* CommandLineToArgvW() */
+
+/* Pop up an out of memory message, returns to Windows */
+static int OutOfMemory(void)
+{
+ SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
+ return -1;
+}
+
+int MINGW32_FORCEALIGN SDL_RunApp(int _argc, char* _argv[], SDL_main_func mainFunction, void * reserved)
+{
+ /* Gets the arguments with GetCommandLine, converts them to argc and argv
+ and calls SDL_main */
+
+ LPWSTR *argvw;
+ char **argv;
+ int i, argc, result;
+
+ (void)_argc; (void)_argv; (void)reserved;
+
+ argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (!argvw) {
+ return OutOfMemory();
+ }
+
+ /* Note that we need to be careful about how we allocate/free memory here.
+ * If the application calls SDL_SetMemoryFunctions(), we can't rely on
+ * SDL_free() to use the same allocator after SDL_main() returns.
+ */
+
+ /* Parse it into argv and argc */
+ argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv));
+ if (!argv) {
+ return OutOfMemory();
+ }
+ for (i = 0; i < argc; ++i) {
+ const int utf8size = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
+ if (!utf8size) { // uhoh?
+ SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+ return -1;
+ }
+
+ argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, utf8size); // this size includes the null-terminator character.
+ if (!argv[i]) {
+ return OutOfMemory();
+ }
+
+ if (WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argv[i], utf8size, NULL, NULL) == 0) { // failed? uhoh!
+ SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+ return -1;
+ }
+ }
+ argv[i] = NULL;
+ LocalFree(argvw);
+
+ SDL_SetMainReady();
+
+ /* Run the application main() code */
+ result = mainFunction(argc, argv);
+
+ /* Free argv, to avoid memory leak */
+ for (i = 0; i < argc; ++i) {
+ HeapFree(GetProcessHeap(), 0, argv[i]);
+ }
+ HeapFree(GetProcessHeap(), 0, argv);
+
+ return result;
+}
+
+#endif /* SDL_PLATFORM_WIN32 */
diff --git a/src/main/winrt/SDL_sysmain_runapp.cpp b/src/main/winrt/SDL_sysmain_runapp.cpp
new file mode 100644
index 0000000000..7a6e347c74
--- /dev/null
+++ b/src/main/winrt/SDL_sysmain_runapp.cpp
@@ -0,0 +1,40 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 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_internal.h"
+
+#include "../../core/winrt/SDL_winrtapp_direct3d.h"
+#include "../../core/winrt/SDL_winrtapp_xaml.h"
+
+#include
+
+extern "C"
+int SDL_RunApp(int, char**, SDL_main_func mainFunction, void * xamlBackgroundPanel)
+{
+ if (xamlBackgroundPanel) {
+ return SDL_WinRTInitXAMLApp(mainFunction, xamlBackgroundPanel);
+ } else {
+ if (FAILED(Windows::Foundation::Initialize(RO_INIT_MULTITHREADED))) {
+ return 1;
+ }
+ return SDL_WinRTInitNonXAMLApp(mainFunction);
+ }
+}
+