mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 15:51:17 +02:00
0e5ea26e36
Only resize when width/height change; love-nx flag mismatches were recreating the EGL surface every frame. Co-authored-by: Cursor <cursoragent@cursor.com>
106 lines
3.2 KiB
Lua
106 lines
3.2 KiB
Lua
-- Switch-only display size: handheld 1280x720, docked (TV) 1920x1080.
|
|
-- love-nx's SDL backend can auto-resize on dock/undock when the window is
|
|
-- resizable; this module also syncs on boot and when the operation mode
|
|
-- changes so a docked launch is not stuck at the conf.lua 720p hint.
|
|
--
|
|
-- Important: only call love.window.setMode when width/height must change.
|
|
-- Re-applying every frame (e.g. to "fix" fullscreen/resizable flags that
|
|
-- love-nx reports differently) recreates the EGL surface and flickers the launcher.
|
|
|
|
local Platform = require("src.core.Platform")
|
|
|
|
local NxDisplay = {}
|
|
|
|
NxDisplay.HANDHELD_W, NxDisplay.HANDHELD_H = 1280, 720
|
|
NxDisplay.DOCKED_W, NxDisplay.DOCKED_H = 1920, 1080
|
|
|
|
-- AppletOperationMode from libnx: Handheld = 0, Console (docked) = 1.
|
|
local MODE_HANDHELD = 0
|
|
local MODE_CONSOLE = 1
|
|
|
|
-- Test hooks (nil = use live Platform / FFI / love.window).
|
|
NxDisplay._forceNXForTests = nil
|
|
NxDisplay._operationModeForTests = nil
|
|
|
|
local ffiOk, ffiC
|
|
|
|
local function ensureFfi()
|
|
if ffiOk ~= nil then return ffiOk end
|
|
ffiOk = false
|
|
local ok, ffi = pcall(require, "ffi")
|
|
if not ok or not ffi then return false end
|
|
-- Redefinition is fine across hot reload / tests; we only need the symbol.
|
|
pcall(ffi.cdef, [[
|
|
unsigned char appletGetOperationMode(void);
|
|
]])
|
|
local probeOk = pcall(function()
|
|
return ffi.C.appletGetOperationMode
|
|
end)
|
|
if not probeOk then return false end
|
|
ffiC = ffi.C
|
|
ffiOk = true
|
|
return true
|
|
end
|
|
|
|
local function isNX()
|
|
if NxDisplay._forceNXForTests ~= nil then
|
|
return not not NxDisplay._forceNXForTests
|
|
end
|
|
return Platform.isNX()
|
|
end
|
|
|
|
-- Returns AppletOperationMode or nil when unavailable.
|
|
function NxDisplay.operationMode()
|
|
if NxDisplay._operationModeForTests ~= nil then
|
|
return NxDisplay._operationModeForTests
|
|
end
|
|
if not ensureFfi() or not ffiC then return nil end
|
|
local ok, mode = pcall(function()
|
|
return tonumber(ffiC.appletGetOperationMode())
|
|
end)
|
|
if not ok then return nil end
|
|
return mode
|
|
end
|
|
|
|
-- Map operation mode → framebuffer size.
|
|
-- Unknown / nil → nil,nil (do not fight SDL or force a wrong size).
|
|
function NxDisplay.desiredSize(mode)
|
|
if mode == nil then mode = NxDisplay.operationMode() end
|
|
if mode == MODE_CONSOLE then
|
|
return NxDisplay.DOCKED_W, NxDisplay.DOCKED_H
|
|
end
|
|
if mode == MODE_HANDHELD then
|
|
return NxDisplay.HANDHELD_W, NxDisplay.HANDHELD_H
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- Apply handheld/dock size when on NX and the window size differs.
|
|
-- Never setMode just to tweak flags — that flickers on love-nx.
|
|
-- Returns true when setMode ran.
|
|
function NxDisplay.sync()
|
|
if not isNX() then return false end
|
|
if not (love and love.window and love.window.getMode and love.window.setMode) then
|
|
return false
|
|
end
|
|
local wantW, wantH = NxDisplay.desiredSize()
|
|
if not wantW or not wantH then return false end
|
|
local curW, curH, flags = love.window.getMode()
|
|
if curW == wantW and curH == wantH then
|
|
return false
|
|
end
|
|
flags = flags or {}
|
|
flags.fullscreen = false
|
|
flags.resizable = true
|
|
love.window.setMode(wantW, wantH, flags)
|
|
return true
|
|
end
|
|
|
|
function NxDisplay._resetForTests()
|
|
NxDisplay._forceNXForTests = nil
|
|
NxDisplay._operationModeForTests = nil
|
|
ffiOk, ffiC = nil, nil
|
|
end
|
|
|
|
return NxDisplay
|