From 67d91c84686a2347ab5963edf56aeb2b2c59ca61 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Sun, 19 Jul 2026 11:28:10 +0100 Subject: [PATCH 1/5] feat(desktop): allow launching in fullscreen Useful for linux handhelds that don't use a window manager --- src/desktop/backends/glfw2.c | 8 ++++---- src/desktop/backends/glfw3.c | 8 +++++++- src/desktop/backends/sdl1.c | 8 ++++++-- src/desktop/backends/sdl2.c | 9 ++++++--- src/desktop/backends/sdl3.c | 5 ++++- src/desktop/main.c | 8 +++++++- src/desktop/platformdefs.h | 2 +- 7 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/desktop/backends/glfw2.c b/src/desktop/backends/glfw2.c index 8debf98dc..9aba1ef2d 100644 --- a/src/desktop/backends/glfw2.c +++ b/src/desktop/backends/glfw2.c @@ -18,7 +18,7 @@ static Runner *g_runner; -static bool tryOpenWindow(int reqW, int reqH) { +static bool tryOpenWindow(int reqW, int reqH, bool fullscreen) { #ifdef GLFW_OPENGL_VERSION_MAJOR if (gfx == SOFTWARE || gfx == LEGACY_GL) { glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 1); @@ -52,7 +52,7 @@ static bool tryOpenWindow(int reqW, int reqH) { return false; #else - return glfwOpenWindow(reqW, reqH, 8, 8, 8, 8, 24, 8, GLFW_WINDOW) != 0; + return glfwOpenWindow(reqW, reqH, 8, 8, 8, 8, 24, 8, fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW) != 0; #endif } @@ -184,7 +184,7 @@ static void GLFWCALL scrollCallback(int pos) { if (g_runner) RunnerMouse_onWheel(g_runner->mouse, yoffset); } -bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) { +bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless, bool fullscreen) { if (headless) { fprintf(stderr, "Headless mode is not supported with GLFW 2\n"); return false; @@ -196,7 +196,7 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) return false; } - if (!tryOpenWindow(reqW, reqH)) { + if (!tryOpenWindow(reqW, reqH, fullscreen)) { fprintf(stderr, "Failed to create GLFW window\n"); glfwTerminate(); return false; diff --git a/src/desktop/backends/glfw3.c b/src/desktop/backends/glfw3.c index 28cba4c2b..fc1d0f336 100644 --- a/src/desktop/backends/glfw3.c +++ b/src/desktop/backends/glfw3.c @@ -220,7 +220,7 @@ static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) { RunnerMouse_onWheel(g_runner->mouse, yoffset); } -bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) { +bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless, bool fullscreen) { // Init GLFW glfwSetErrorCallback(glfwErrorCallback); if (!glfwInit()) { @@ -269,6 +269,12 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) // We set the window size AFTER the window creation so we can use glfwGetWindowContentScale platformSetWindowSize(reqW, reqH); + if (fullscreen) { + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); + } + // Set up keyboard input glfwSetKeyCallback(window, keyCallback); glfwSetCharCallback(window, characterCallback); diff --git a/src/desktop/backends/sdl1.c b/src/desktop/backends/sdl1.c index c416ab16b..d98280238 100644 --- a/src/desktop/backends/sdl1.c +++ b/src/desktop/backends/sdl1.c @@ -238,7 +238,7 @@ static bool platformGetWindowFocus(void) { return SDL_GetAppState() & SDL_APPINPUTFOCUS; } -bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) { +bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless, bool fullscreen) { if (headless && gfx != SOFTWARE) { fprintf(stderr, "Headless mode on SDL 1.2 requires the software renderer!\n"); return false; @@ -267,7 +267,11 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) fbWidth = reqW; fbHeight = reqH; if(!headless) { - scr = SDL_SetVideoMode(fbWidth, fbHeight, 0, (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_RESIZABLE); + Uint32 videoFlags = (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_RESIZABLE; + if (fullscreen) { + videoFlags = (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_FULLSCREEN; + } + scr = SDL_SetVideoMode(fbWidth, fbHeight, 0, videoFlags); if (!scr && gfx == SOFTWARE) { SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN); if (modes && modes != (SDL_Rect**) -1 && modes[0]) { diff --git a/src/desktop/backends/sdl2.c b/src/desktop/backends/sdl2.c index e4549db1b..5a14b9d73 100644 --- a/src/desktop/backends/sdl2.c +++ b/src/desktop/backends/sdl2.c @@ -130,10 +130,9 @@ bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH) { } static float platformGetWindowScale(void) { - if (!scale_x || !scale_y) return; int32_t draw_w, draw_h; int logical_w, logical_h; - platformGetWindowSize(&draw_w, &draw_h); + if (!platformGetWindowSize(&draw_w, &draw_h)) return 1.0f; SDL_GetWindowSize(window, &logical_w, &logical_h); return (logical_h > 0) ? (float)draw_h / logical_h : 1.0f; } @@ -161,7 +160,7 @@ static bool platformGetWindowFocus(void) { return SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS; } -bool platformInit(int reqW, int reqH, const char *title, bool headless) { +bool platformInit(int reqW, int reqH, const char *title, bool headless, bool fullscreen) { // Init SDL if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_GAMECONTROLLER)) { fprintf(stderr, "Failed to initialize SDL\n"); @@ -213,6 +212,10 @@ bool platformInit(int reqW, int reqH, const char *title, bool headless) { } else { scr = SDL_GetWindowSurface(window); } + + if (fullscreen) + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + // If we don't do this, the window will be larger than it should be on HiDPI displays. platformSetWindowSize(reqW, reqH); diff --git a/src/desktop/backends/sdl3.c b/src/desktop/backends/sdl3.c index 7cf229eb8..2e293984e 100644 --- a/src/desktop/backends/sdl3.c +++ b/src/desktop/backends/sdl3.c @@ -146,7 +146,7 @@ static bool platformGetWindowFocus(void) { return SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS; } -bool platformInit(int reqW, int reqH, const char *title, bool headless) { +bool platformInit(int reqW, int reqH, const char *title, bool headless, bool fullscreen) { // Init SDL if (!SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMEPAD)) { fprintf(stderr, "Failed to initialize SDL\n"); @@ -190,6 +190,9 @@ bool platformInit(int reqW, int reqH, const char *title, bool headless) { } else scr = SDL_GetWindowSurface(window); + if (fullscreen) + SDL_SetWindowFullscreen(window, true); + return true; } diff --git a/src/desktop/main.c b/src/desktop/main.c index 085830abc..575fab780 100644 --- a/src/desktop/main.c +++ b/src/desktop/main.c @@ -224,6 +224,7 @@ typedef struct { bool alwaysLogUnknownFunctions; bool alwaysLogStubbedFunctions; bool headless; + bool fullscreen; bool traceFrames; bool printRooms; bool printObjects; @@ -425,6 +426,7 @@ static void printUsage(const char *argv0) { " --record-inputs - Record all keyboard inputs to a file\n" " --playback-inputs - Playback input from file\n" " --renderer - Set the rendering API\n" + " --fullscreen - Launch in fullscreen mode\n" " --lazy-rooms - Lazily load rooms, increases load times but reduces memory usage\n" " --eager-room - When --lazy-rooms is set, keep these rooms always in memory\n" " --os-type - Set the reported OS type\n" @@ -484,6 +486,7 @@ static void parseCommandLineArgs(CommandLineArgs* args, int argc, char* argv[]) {"record-inputs", required_argument, nullptr, 'I'}, {"playback-inputs", required_argument, nullptr, 'P'}, {"renderer", required_argument, nullptr, 'g'}, + {"fullscreen", no_argument, nullptr, 4101}, {"lazy-rooms", no_argument, nullptr, 'z'}, {"eager-room", required_argument, nullptr, 'G'}, {"os-type", required_argument, nullptr, 'O'}, @@ -678,6 +681,9 @@ static void parseCommandLineArgs(CommandLineArgs* args, int argc, char* argv[]) case 'g': args->renderer = optarg; break; + case 4101: + args->fullscreen = true; + break; case 'z': args->lazyRooms = true; break; @@ -1321,7 +1327,7 @@ int main(int argc, char* argv[]) { resolveWindowSize(&args, gen8->defaultWindowWidth, gen8->defaultWindowHeight, &windowW, &windowH); if (!platformInitialized) { - if (!platformInit(windowW, windowH, windowTitle, args.headless)) { + if (!platformInit(windowW, windowH, windowTitle, args.headless, args.fullscreen)) { DataWin_free(dataWin); freeCommandLineArgs(&args); return 1; diff --git a/src/desktop/platformdefs.h b/src/desktop/platformdefs.h index ad93f4b81..e3b5d3bb0 100644 --- a/src/desktop/platformdefs.h +++ b/src/desktop/platformdefs.h @@ -6,7 +6,7 @@ #include "runner.h" #include "input_recording.h" -bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless); +bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless, bool fullscreen); void platformInitFunctions(Runner *); void platformExit(void); void platformSwapBuffers(void); From d44b2ece618d16795dc734cbb4044c12438a199f Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 22 Jul 2026 23:16:43 +0100 Subject: [PATCH 2/5] impl window_set_fullscreen, window_get_fullscreen stubs on console, active on desktop except maybe GLFW2 --- src/desktop/backends/glfw2.c | 11 ++++++++++- src/desktop/backends/glfw3.c | 25 ++++++++++++++++++++----- src/desktop/backends/sdl1.c | 24 +++++++++++++++--------- src/desktop/backends/sdl2.c | 11 +++++++++-- src/desktop/backends/sdl3.c | 11 +++++++++-- src/desktop/main.c | 2 ++ src/desktop/platformdefs.h | 2 ++ src/ps2/main.c | 16 +++++++++++++++- src/ps3/main.c | 15 ++++++++++++++- src/runner.h | 2 ++ src/vm_builtins.c | 22 +++++++++++++++++++--- 11 files changed, 117 insertions(+), 24 deletions(-) diff --git a/src/desktop/backends/glfw2.c b/src/desktop/backends/glfw2.c index 9aba1ef2d..146705463 100644 --- a/src/desktop/backends/glfw2.c +++ b/src/desktop/backends/glfw2.c @@ -29,7 +29,7 @@ static bool tryOpenWindow(int reqW, int reqH, bool fullscreen) { for (size_t i = 0; i < sizeof(GLCommon_versions)/sizeof(GLCommon_versions[0]); i++) { glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, GLCommon_versions[i].major); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, GLCommon_versions[i].minor); - + if (GLCommon_versions[i].major >= 3) { glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); if (GLCommon_versions[i].major == 3 && GLCommon_versions[i].minor == 2) { @@ -95,6 +95,15 @@ static bool platformGetWindowFocus(void) { return glfwGetWindowParam(GLFW_ACTIVE); } +bool platformGetWindowFullscreen(void) { + return glfw2Fullscreen; +} + +void platformSetWindowFullscreen(bool fullscreen) { + if (fullscreen == glfw2Fullscreen) return; + glfw2Fullscreen = fullscreen; +} + static int32_t glfwKeyToGml(int glfwKey) { // Letters and numbers are the same as GML if (glfwKey >= 'A' && glfwKey <= 'Z') return glfwKey; diff --git a/src/desktop/backends/glfw3.c b/src/desktop/backends/glfw3.c index fc1d0f336..9f42c2935 100644 --- a/src/desktop/backends/glfw3.c +++ b/src/desktop/backends/glfw3.c @@ -126,6 +126,25 @@ static bool platformGetWindowFocus(void) { return glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0; } +static int windowedX, windowedY, windowedW, windowedH; + +bool platformGetWindowFullscreen(void) { + return glfwGetWindowMonitor(window) != NULL; +} + +void platformSetWindowFullscreen(bool fullscreen) { + if (fullscreen == platformGetWindowFullscreen()) return; + if (fullscreen) { + glfwGetWindowPos(window, &windowedX, &windowedY); + glfwGetWindowSize(window, &windowedW, &windowedH); + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); + } else { + glfwSetWindowMonitor(window, NULL, windowedX, windowedY, windowedW, windowedH, 0); + } +} + static void glfwErrorCallback(int code, const char* description) { fprintf(stderr, "GLFW error 0x%x: %s\n", code, description); } @@ -269,11 +288,7 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless, // We set the window size AFTER the window creation so we can use glfwGetWindowContentScale platformSetWindowSize(reqW, reqH); - if (fullscreen) { - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(monitor); - glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); - } + platformSetWindowFullscreen(fullscreen); // Set up keyboard input glfwSetKeyCallback(window, keyCallback); diff --git a/src/desktop/backends/sdl1.c b/src/desktop/backends/sdl1.c index d98280238..f50ac45ed 100644 --- a/src/desktop/backends/sdl1.c +++ b/src/desktop/backends/sdl1.c @@ -238,6 +238,15 @@ static bool platformGetWindowFocus(void) { return SDL_GetAppState() & SDL_APPINPUTFOCUS; } +bool platformGetWindowFullscreen(void) { + return scr ? (scr->flags & SDL_FULLSCREEN) : false; +} + +void platformSetWindowFullscreen(bool fullscreen) { + if (fullscreen == platformGetWindowFullscreen()) return; + SDL_WM_ToggleFullScreen(scr); +} + bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless, bool fullscreen) { if (headless && gfx != SOFTWARE) { fprintf(stderr, "Headless mode on SDL 1.2 requires the software renderer!\n"); @@ -267,10 +276,7 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless, fbWidth = reqW; fbHeight = reqH; if(!headless) { - Uint32 videoFlags = (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_RESIZABLE; - if (fullscreen) { - videoFlags = (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_FULLSCREEN; - } + Uint32 videoFlags = (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_RESIZABLE | (fullscreen ? SDL_FULLSCREEN : 0); scr = SDL_SetVideoMode(fbWidth, fbHeight, 0, videoFlags); if (!scr && gfx == SOFTWARE) { SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN); @@ -420,11 +426,11 @@ static void platformResetJoysticks(void) { openJoysticks[i] = NULL; } } - + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); SDL_InitSubSystem(SDL_INIT_JOYSTICK); SDL_JoystickEventState(SDL_IGNORE); - + int numJoysticks = SDL_NumJoysticks(); bool needsRemap = false; for (int i = 0; i < numJoysticks && i < MAX_GAMEPADS; i++) { @@ -436,11 +442,11 @@ static void platformResetJoysticks(void) { needsRemap = true; } } - + for (int i = numJoysticks; i < MAX_GAMEPADS; i++) { joystickMappings[i].valid = false; } - + if (needsRemap) { loadGamepadMappings(); } @@ -506,7 +512,7 @@ bool platformHandleEvents(void) { float norm = val / 32767.0f; if (map->axis_button_sign[btn] < 0) norm = -norm; if (norm < 0.0f) norm = 0.0f; - + if (norm > slot->buttonValue[btn]) { slot->buttonValue[btn] = norm; } diff --git a/src/desktop/backends/sdl2.c b/src/desktop/backends/sdl2.c index 5a14b9d73..eeb6b9230 100644 --- a/src/desktop/backends/sdl2.c +++ b/src/desktop/backends/sdl2.c @@ -160,6 +160,14 @@ static bool platformGetWindowFocus(void) { return SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS; } +bool platformGetWindowFullscreen(void) { + return SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP; +} + +void platformSetWindowFullscreen(bool fullscreen) { + SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); +} + bool platformInit(int reqW, int reqH, const char *title, bool headless, bool fullscreen) { // Init SDL if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_GAMECONTROLLER)) { @@ -213,8 +221,7 @@ bool platformInit(int reqW, int reqH, const char *title, bool headless, bool ful scr = SDL_GetWindowSurface(window); } - if (fullscreen) - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + platformSetWindowFullscreen(fullscreen); // If we don't do this, the window will be larger than it should be on HiDPI displays. platformSetWindowSize(reqW, reqH); diff --git a/src/desktop/backends/sdl3.c b/src/desktop/backends/sdl3.c index 2e293984e..3fd9c110d 100644 --- a/src/desktop/backends/sdl3.c +++ b/src/desktop/backends/sdl3.c @@ -146,6 +146,14 @@ static bool platformGetWindowFocus(void) { return SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS; } +bool platformGetWindowFullscreen(void) { + return SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN; +} + +void platformSetWindowFullscreen(bool fullscreen) { + SDL_SetWindowFullscreen(window, fullscreen); +} + bool platformInit(int reqW, int reqH, const char *title, bool headless, bool fullscreen) { // Init SDL if (!SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMEPAD)) { @@ -190,8 +198,7 @@ bool platformInit(int reqW, int reqH, const char *title, bool headless, bool ful } else scr = SDL_GetWindowSurface(window); - if (fullscreen) - SDL_SetWindowFullscreen(window, true); + platformSetWindowFullscreen(fullscreen); return true; } diff --git a/src/desktop/main.c b/src/desktop/main.c index 575fab780..7b7e0c2f2 100644 --- a/src/desktop/main.c +++ b/src/desktop/main.c @@ -1424,6 +1424,8 @@ int main(int argc, char* argv[]) { runner->setWindowSize = platformSetWindowSize; runner->getWindowSize = platformGetWindowSize; runner->setWindowTitle = platformSetWindowTitle; + runner->getWindowFullscreen = platformGetWindowFullscreen; + runner->setWindowFullscreen = platformSetWindowFullscreen; Runner_setGameArgs(runner, currentGameArgs, (int32_t) arrlen(currentGameArgs)); platformInitFunctions(runner); diff --git a/src/desktop/platformdefs.h b/src/desktop/platformdefs.h index e3b5d3bb0..f9879d246 100644 --- a/src/desktop/platformdefs.h +++ b/src/desktop/platformdefs.h @@ -18,6 +18,8 @@ bool platformGetWindowSize(int32_t* outW, int32_t* outH); bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH); void platformSetWindowSize(int32_t width, int32_t height); void platformSetWindowTitle(const char* title); +bool platformGetWindowFullscreen(void); +void platformSetWindowFullscreen(bool fullscreen); void platformSleepUntil(uint64_t time); enum GraphicsAPI { diff --git a/src/ps2/main.c b/src/ps2/main.c index 1a13127d6..ac1ed8201 100644 --- a/src/ps2/main.c +++ b/src/ps2/main.c @@ -88,6 +88,16 @@ static bool padWasStable[2] = {false, false}; // Whether the controllers should be exposed via the GameMaker gamepad API static bool gamepadApiEnabled = false; +// Always assume fullscreen for PS2 +static bool getWindowFullscreen() { + return true; +} + +// No-op for PS2 +static void setWindowFullscreen(bool fullscreen) { + (void)fullscreen; +} + static void parsePadMappings(JsonValue* configRoot, const char* key, PadMapping** outMappings, int* outCount, const char* logLabel) { JsonValue* mappingsObj = JsonReader_getJsonValueByKey(configRoot, key); if (mappingsObj == nullptr || !JsonReader_isObject(mappingsObj)) return; @@ -431,7 +441,7 @@ int main(int argc, char* argv[]) { options.eagerlyLoadedRooms = eagerRooms; options.progressCallback = PS2Overlay_statusScreenCallback; options.progressCallbackUserData = PS2Overlay_getCallbackData(); - + DataWin* dataWin = DataWin_parse(dataWinPath, options); free(dataWinPath); shfree(eagerRooms); @@ -489,6 +499,10 @@ int main(int argc, char* argv[]) { PS2Overlay_drawStatusScreen(dataWin->gen8.displayName, "Creating runner...", true); Runner* runner = Runner_create(dataWin, vm, renderer, fileSystem, audioSystem); + // Set fullscreen stubs + runner->getWindowFullscreen = getWindowFullscreen; + runner->setWindowFullscreen = setWindowFullscreen; + // Parse disabledObjects from CONFIG.JSN JsonValue* disabledObjectsArr = JsonReader_getJsonValueByKey(configRoot, "disabledObjects"); if (disabledObjectsArr != nullptr && JsonReader_isArray(disabledObjectsArr)) { diff --git a/src/ps3/main.c b/src/ps3/main.c index 4eabdb9a1..18494c8c7 100644 --- a/src/ps3/main.c +++ b/src/ps3/main.c @@ -80,6 +80,15 @@ const StickMapping STICK_MAPPINGS[] = { #define STICK_MAPPING_COUNT (sizeof(STICK_MAPPINGS) / sizeof(STICK_MAPPINGS[0])) static bool prevStickState[sizeof(STICK_MAPPINGS) / sizeof(STICK_MAPPINGS[0])] = {0}; +// ===[ FULLSCREEN STUBS ]=== +static bool getWindowFullscreen() { + return true; +} + +static void setWindowFullscreen(bool fullscreen) { + (void)fullscreen; +} + // ===[ MAIN ]=== static double freq = 0; #define PS3_GET_TIME ((double)__builtin_ppc_get_timebase() / (double)freq) @@ -94,7 +103,7 @@ static void sys_callback(uint64_t status, uint64_t param, void* userdata) { case SYSUTIL_EXIT_GAME: shouldExit = true; break; - + case SYSUTIL_MENU_OPEN: case SYSUTIL_MENU_CLOSE: break; @@ -293,6 +302,10 @@ int main(int argc, char* argv[]) { runner->debugMode = false; //runner->osType = OS_PS3; + // Set fullscreen stubs + runner->getWindowFullscreen = getWindowFullscreen; + runner->setWindowFullscreen = setWindowFullscreen; + // Initialize the first room and fire Game Start / Room Start events Runner_initFirstRoom(runner); diff --git a/src/runner.h b/src/runner.h index 78bbfaa87..abca5d9a8 100644 --- a/src/runner.h +++ b/src/runner.h @@ -503,6 +503,8 @@ struct Runner { bool (*getWindowSize)(int32_t* outW, int32_t* outH); void (*setWindowSize)(int32_t width, int32_t height); bool (*windowHasFocus)(void); + bool (*getWindowFullscreen)(void); + void (*setWindowFullscreen)(bool fullscreen); void (*setCursor)(int32_t cursorType); int32_t currentCursor; // last value passed to window_set_cursor TileLayerMapEntry* tileLayerMap; // stb_ds hashmap: depth -> tile layer state diff --git a/src/vm_builtins.c b/src/vm_builtins.c index ad61091e4..9edd62f4f 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -7770,9 +7770,25 @@ static RValue builtin_joystick_axes(VMContext* ctx, RValue* args, MAYBE_UNUSED i return RValue_makeReal(RunnerGamepad_getAxisCount(runner->gamepads, id)); } -// Window stubs -STUB_RETURN_ZERO(window_get_fullscreen) -STUB_RETURN_UNDEFINED(window_set_fullscreen) +static RValue builtin_window_get_fullscreen(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { + Runner* runner = ctx->runner; + if (runner != nullptr && runner->getWindowFullscreen != nullptr) { + return RValue_makeBool(runner->getWindowFullscreen()); + } + return RValue_makeBool(false); +} + +static RValue builtin_window_set_fullscreen(VMContext* ctx, RValue* args, MAYBE_UNUSED int32_t argCount) { + if (argCount < 1) return RValue_makeUndefined(); + Runner* runner = ctx->runner; + if (runner == nullptr) return RValue_makeUndefined(); + bool fullscreen = RValue_toBool(args[0]); + if (runner->setWindowFullscreen != nullptr) { + runner->setWindowFullscreen(fullscreen); + } + return RValue_makeUndefined(); +} + static RValue builtin_window_get_width(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE_UNUSED int32_t argCount) { Runner* runner = ctx->runner; if (runner != nullptr && runner->getWindowSize != nullptr) { From fea69862bb27bc3a36058cbc09f48a8134dfc47c Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 22 Jul 2026 23:21:10 +0100 Subject: [PATCH 3/5] for the 3 people who still use glfw2 --- src/desktop/backends/glfw2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/desktop/backends/glfw2.c b/src/desktop/backends/glfw2.c index 146705463..29dcd54ef 100644 --- a/src/desktop/backends/glfw2.c +++ b/src/desktop/backends/glfw2.c @@ -91,6 +91,8 @@ void platformGetMousePos(double *xPos, double *yPos) { *yPos = (double)my; } +static bool glfw2Fullscreen = false; + static bool platformGetWindowFocus(void) { return glfwGetWindowParam(GLFW_ACTIVE); } From 7fb9bf5b01875c5790949b27188e4ec4b236e165 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 22 Jul 2026 23:22:14 +0100 Subject: [PATCH 4/5] assume true if getWindowFullscreen is nullptr --- src/vm_builtins.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vm_builtins.c b/src/vm_builtins.c index 9edd62f4f..d726ef1cf 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3638,7 +3638,7 @@ static RValue builtin_camera_set_view_angle(VMContext* ctx, RValue* args, int32_ if (2 > argCount) return RValue_makeUndefined(); Runner* runner = ctx->runner; GMLCamera* camera = Runner_getCameraById(runner, RValue_toInt32(args[0])); - if (camera != nullptr) { + if (camera != nullptr) { camera->viewAngle = (float) RValue_toReal(args[1]); Runner_updateCameraViewSimple(camera); } @@ -3706,7 +3706,7 @@ static RValue builtin_camera_create_view(VMContext* ctx, RValue* args, int32_t a if (argCount > 9) camera->borderY = (uint32_t) RValue_toInt32(args[9]); Runner_updateCameraViewSimple(camera); - + return RValue_makeReal(id); } @@ -7775,7 +7775,7 @@ static RValue builtin_window_get_fullscreen(VMContext* ctx, MAYBE_UNUSED RValue* if (runner != nullptr && runner->getWindowFullscreen != nullptr) { return RValue_makeBool(runner->getWindowFullscreen()); } - return RValue_makeBool(false); + return RValue_makeBool(true); } static RValue builtin_window_set_fullscreen(VMContext* ctx, RValue* args, MAYBE_UNUSED int32_t argCount) { @@ -16223,7 +16223,7 @@ static RValue builtin_sprite_get_info(VMContext* ctx, RValue* args, int32_t argC Instance* frame = Runner_createStruct(ctx->runner); int32_t idx = sprite->tpagIndices[i]; TexturePageItem* tpagItem = &ctx->dataWin->tpag.items[idx]; - + VM_structSetAndFreeVal(ctx, frame, "w", RValue_makeReal(tpagItem->boundingWidth), -1); VM_structSetAndFreeVal(ctx, frame, "h", RValue_makeReal(tpagItem->boundingHeight), -1); VM_structSetAndFreeVal(ctx, frame, "x_offset", RValue_makeReal(tpagItem->targetX), -1); @@ -16235,7 +16235,7 @@ static RValue builtin_sprite_get_info(VMContext* ctx, RValue* args, int32_t argC VM_structSetAndFreeVal(ctx, frame, "crop_width", RValue_makeReal(tpagItem->targetWidth), -1); VM_structSetAndFreeVal(ctx, frame, "crop_height", RValue_makeReal(tpagItem->targetHeight), -1); VM_structSetAndFreeVal(ctx, frame, "texture", RValue_makeReal(idx), -1); - + *GMLArray_slot(frames, (int32_t)i) = RValue_makeStructAndIncRef(frame); } VM_structSetAndFreeVal(ctx, ret, "frames", RValue_makeArray(frames), -1); @@ -16357,7 +16357,7 @@ void VMBuiltins_registerAll(VMContext* ctx) { VM_registerBuiltin(ctx, "matrix_build_projection_ortho", builtin_matrix_build_projection_ortho); VM_registerBuiltin(ctx, "matrix_build_projection_perspective_fov", builtin_matrix_build_projection_perspective_fov); VM_registerBuiltin(ctx, "matrix_get", builtin_matrix_get); - VM_registerBuiltin(ctx, "matrix_set", builtin_matrix_set); + VM_registerBuiltin(ctx, "matrix_set", builtin_matrix_set); // Random VM_registerBuiltin(ctx, "random", builtin_random); VM_registerBuiltin(ctx, "random_range", builtin_random_range); From 1a3b8c284f7514d2ba15dceddd1ec8ded7ca2bc2 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 22 Jul 2026 23:23:13 +0100 Subject: [PATCH 5/5] remove fullscreen stubs from console --- src/ps2/main.c | 14 -------------- src/ps3/main.c | 13 ------------- 2 files changed, 27 deletions(-) diff --git a/src/ps2/main.c b/src/ps2/main.c index ac1ed8201..147c04eb6 100644 --- a/src/ps2/main.c +++ b/src/ps2/main.c @@ -88,16 +88,6 @@ static bool padWasStable[2] = {false, false}; // Whether the controllers should be exposed via the GameMaker gamepad API static bool gamepadApiEnabled = false; -// Always assume fullscreen for PS2 -static bool getWindowFullscreen() { - return true; -} - -// No-op for PS2 -static void setWindowFullscreen(bool fullscreen) { - (void)fullscreen; -} - static void parsePadMappings(JsonValue* configRoot, const char* key, PadMapping** outMappings, int* outCount, const char* logLabel) { JsonValue* mappingsObj = JsonReader_getJsonValueByKey(configRoot, key); if (mappingsObj == nullptr || !JsonReader_isObject(mappingsObj)) return; @@ -499,10 +489,6 @@ int main(int argc, char* argv[]) { PS2Overlay_drawStatusScreen(dataWin->gen8.displayName, "Creating runner...", true); Runner* runner = Runner_create(dataWin, vm, renderer, fileSystem, audioSystem); - // Set fullscreen stubs - runner->getWindowFullscreen = getWindowFullscreen; - runner->setWindowFullscreen = setWindowFullscreen; - // Parse disabledObjects from CONFIG.JSN JsonValue* disabledObjectsArr = JsonReader_getJsonValueByKey(configRoot, "disabledObjects"); if (disabledObjectsArr != nullptr && JsonReader_isArray(disabledObjectsArr)) { diff --git a/src/ps3/main.c b/src/ps3/main.c index 18494c8c7..45a57d92b 100644 --- a/src/ps3/main.c +++ b/src/ps3/main.c @@ -80,15 +80,6 @@ const StickMapping STICK_MAPPINGS[] = { #define STICK_MAPPING_COUNT (sizeof(STICK_MAPPINGS) / sizeof(STICK_MAPPINGS[0])) static bool prevStickState[sizeof(STICK_MAPPINGS) / sizeof(STICK_MAPPINGS[0])] = {0}; -// ===[ FULLSCREEN STUBS ]=== -static bool getWindowFullscreen() { - return true; -} - -static void setWindowFullscreen(bool fullscreen) { - (void)fullscreen; -} - // ===[ MAIN ]=== static double freq = 0; #define PS3_GET_TIME ((double)__builtin_ppc_get_timebase() / (double)freq) @@ -302,10 +293,6 @@ int main(int argc, char* argv[]) { runner->debugMode = false; //runner->osType = OS_PS3; - // Set fullscreen stubs - runner->getWindowFullscreen = getWindowFullscreen; - runner->setWindowFullscreen = setWindowFullscreen; - // Initialize the first room and fire Game Start / Room Start events Runner_initFirstRoom(runner);