Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/SDL3/SDL_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetMainReady(void);
* using SDL_main (like when using SDL_MAIN_HANDLED). When using this, you do
* *not* need SDL_SetMainReady().
*
* If `argv` is NULL, SDL will provide command line arguments, either by
* querying the OS for them if possible, or supplying a filler array if not.
*
* \param argc the argc parameter from the application's main() function, or 0
* if the platform's main-equivalent has no argc.
* \param argv the argv parameter from the application's main() function, or
Expand Down
10 changes: 10 additions & 0 deletions src/main/SDL_main_callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,13 @@ void SDL_QuitMainCallbacks(SDL_AppResult result)
SDL_Quit();
}

void SDL_CheckDefaultArgcArgv(int *argc, char ***argv)
{
if (!argv)
{
static char dummyargv0[] = { 'S', 'D', 'L', '_', 'a', 'p', 'p', '\0' };
static char *argvdummy[2] = { dummyargv0, NULL };
*argc = 1;
*argv = argvdummy;
}
}
4 changes: 4 additions & 0 deletions src/main/SDL_main_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ SDL_AppResult SDL_InitMainCallbacks(int argc, char *argv[], SDL_AppInit_func app
SDL_AppResult SDL_IterateMainCallbacks(bool pump_events);
void SDL_QuitMainCallbacks(SDL_AppResult result);

// (not a callback thing, but convenient to stick this in here.)
// If *_argv is NULL, update *_argc and *_argv to point at a static array of { "SDL_app", NULL }.
void SDL_CheckDefaultArgcArgv(int *_argc, char ***_argv);

#endif // SDL_main_callbacks_h_


12 changes: 2 additions & 10 deletions src/main/SDL_runapp.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_main_callbacks.h"

/* Most platforms that use/need SDL_main have their own SDL_RunApp() implementation.
* If not, you can special case it here by appending || defined(__YOUR_PLATFORM__) */
Expand All @@ -27,16 +28,7 @@
int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserved)
{
(void)reserved;

if(!argv)
{
// make sure argv isn't NULL, in case some user code doesn't like that
static char dummyargv0[] = { 'S', 'D', 'L', '_', 'a', 'p', 'p', '\0' };
static char *argvdummy[2] = { dummyargv0, NULL };
argc = 1;
argv = argvdummy;
}

SDL_CheckDefaultArgcArgv(&argc, &argv);
return mainFunction(argc, argv);
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/emscripten/SDL_sysmain_runapp.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#ifdef SDL_PLATFORM_EMSCRIPTEN

#include "../SDL_main_callbacks.h"

#include <emscripten/emscripten.h>

EM_JS_DEPS(sdlrunapp, "$dynCall,$stringToNewUTF8");
Expand All @@ -35,6 +37,8 @@ int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserv
{
(void)reserved;

SDL_CheckDefaultArgcArgv(&argc, &argv);

// Move any URL params that start with "SDL_" over to environment
// variables, so the hint system can pick them up, etc, much like a user
// can set them from a shell prompt on a desktop machine. Ignore all
Expand Down
84 changes: 42 additions & 42 deletions src/main/gdk/SDL_sysmain_runapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,53 +37,52 @@ static BOOL OutOfMemory(void)
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)
int SDL_RunApp(int _argc, char **_argv, 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;
char **allocated_argv = NULL;
char **argv = _argv;
int argc = _argc;

if (!argv) {
// Get the arguments with GetCommandLine, convert them to argc and argv
LPWSTR *argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
if (argvw == NULL) {
return OutOfMemory();
}

argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, utf8size); // this size includes the null-terminator character.
if (!argv[i]) {
// 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.

argv = allocated_argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv));
if (argv == NULL) {
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;
for (int 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[argc] = NULL;
LocalFree(argvw);
}
argv[i] = NULL;
LocalFree(argvw);

hr = XGameRuntimeInitialize();
int result = -1;
XTaskQueueHandle taskQueue;
HRESULT hr = XGameRuntimeInitialize();

if (SUCCEEDED(hr) && SDL_GetGDKTaskQueue(&taskQueue)) {
Uint32 titleid = 0;
Expand Down Expand Up @@ -134,14 +133,15 @@ int SDL_RunApp(int, char **, SDL_main_func mainFunction, void *reserved)
#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]);
if (allocated_argv) {
for (int i = 0; i < argc; ++i) {
HeapFree(GetProcessHeap(), 0, allocated_argv[i]);
}
HeapFree(GetProcessHeap(), 0, allocated_argv);
}
HeapFree(GetProcessHeap(), 0, argv);

return result;
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/n3ds/SDL_sysmain_runapp.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,16 @@

#ifdef SDL_PLATFORM_3DS

#include "../SDL_main_callbacks.h"

#include <3ds.h>

int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserved)
{
int result;

SDL_CheckDefaultArgcArgv(&argc, &argv);

// init
osSetSpeedupEnable(true);
romfsInit();
Expand Down
4 changes: 4 additions & 0 deletions src/main/ps2/SDL_sysmain_runapp.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

// SDL_RunApp() code for PS2 based on SDL_ps2_main.c, fjtrujy@gmail.com

#include "../SDL_main_callbacks.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
Expand Down Expand Up @@ -69,6 +71,8 @@ int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserv
int res;
(void)reserved;

SDL_CheckDefaultArgcArgv(&argc, &argv);

prepare_IOP();
init_drivers();

Expand Down
4 changes: 4 additions & 0 deletions src/main/psp/SDL_sysmain_runapp.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <pspkernel.h>
#include <pspthreadman.h>
#include "../../events/SDL_events_c.h"
#include "../SDL_main_callbacks.h"

/* If application's main() is redefined as SDL_main, and libSDL_main is
linked, then this file will create the standard exit callback,
Expand Down Expand Up @@ -72,6 +73,9 @@ int sdl_psp_setup_callbacks(void)
int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void * reserved)
{
(void)reserved;

SDL_CheckDefaultArgcArgv(&argc, &argv);

sdl_psp_setup_callbacks();

SDL_SetMainReady();
Expand Down
9 changes: 5 additions & 4 deletions src/video/uikit/SDL_uikitappdelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#import "SDL_uikitwindow.h"

#include "../../events/SDL_events_c.h"
#include "../../main/SDL_main_callbacks.h"

#ifdef main
#undef main
Expand All @@ -41,7 +42,7 @@

int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void *reserved)
{
int i;
SDL_CheckDefaultArgcArgv(&argc, &argv);

// store arguments
/* Note that we need to be careful about how we allocate/free memory here.
Expand All @@ -51,11 +52,11 @@ int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void *reserve
forward_main = mainFunction;
forward_argc = argc;
forward_argv = (char **)malloc((argc + 1) * sizeof(char *)); // This should NOT be SDL_malloc()
for (i = 0; i < argc; i++) {
for (int i = 0; i < argc; i++) {
forward_argv[i] = malloc((strlen(argv[i]) + 1) * sizeof(char)); // This should NOT be SDL_malloc()
strcpy(forward_argv[i], argv[i]);
}
forward_argv[i] = NULL;
forward_argv[argc] = NULL;

// Give over control to run loop, SDLUIKitDelegate will handle most things from here
@autoreleasepool {
Expand All @@ -71,7 +72,7 @@ int SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void *reserve
}

// free the memory we used to hold copies of argc and argv
for (i = 0; i < forward_argc; i++) {
for (int i = 0; i < forward_argc; i++) {
free(forward_argv[i]); // This should NOT be SDL_free()
}
free(forward_argv); // This should NOT be SDL_free()
Expand Down
Loading