mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 15:51:17 +02:00
feat(switch): switch handheld 720p / docked 1080p at runtime
Unlock love-nx SDL dock/undock resizing and sync via NxDisplay so booting docked is not stuck on the conf 720p hint. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
-- 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 every frame so a docked
|
||||
-- launch is not stuck at the conf.lua 720p hint until the next mode change.
|
||||
|
||||
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 → handheld 720p.
|
||||
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
|
||||
return NxDisplay.HANDHELD_W, NxDisplay.HANDHELD_H
|
||||
end
|
||||
|
||||
-- Apply handheld/dock size when on NX and the window differs. No-op elsewhere.
|
||||
-- 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()
|
||||
local curW, curH, flags = love.window.getMode()
|
||||
flags = flags or {}
|
||||
if curW == wantW and curH == wantH
|
||||
and flags.fullscreen == false and flags.resizable == true then
|
||||
return false
|
||||
end
|
||||
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
|
||||
Reference in New Issue
Block a user