diff --git a/build-rg34xxsp.sh b/build-rg34xxsp.sh index efa9db73..44dbac4c 100755 --- a/build-rg34xxsp.sh +++ b/build-rg34xxsp.sh @@ -202,6 +202,11 @@ export LD_LIBRARY_PATH="$GAMEDIR/libs.aarch64:${LD_LIBRARY_PATH:-}" export SDL_GAMECONTROLLERCONFIG="${sdl_controllerconfig:-}" # Mali / H700: prefer GLES where available export LOVE_GRAPHICS_USE_OPENGLES="${LOVE_GRAPHICS_USE_OPENGLES:-1}" +# Same GPU class as a phone, but getOS() here says "Linux", so the Android +# gate (issue #136) would not fire on its own: refuse GBC FX explicitly. +# Hides the OPTIONS row, pins the level to OFF, and heals a level already +# persisted in options.lua. +export POKEPORT_GBCFX="${POKEPORT_GBCFX:-0}" $ESUDO chmod a+x ./bin/love.aarch64 2>/dev/null || chmod a+x ./bin/love.aarch64 $ESUDO chmod 666 /dev/uinput 2>/dev/null || true @@ -292,6 +297,13 @@ Native LÖVE 11.5 port of gen1recomp for Anbernic RG34XXSP on In-game controls use the normal PortMaster / SDL pad map (rebind under OPTIONS → CONTROLS). +### Display options + +GBC FX is disabled on this device (the H700's Mali GPU compiles that present +pass and then shows a black frame), so the OPTIONS row is hidden. COLORS, +TILT, ZOOM, VOID FILL and MAX FPS all work. To try it anyway, launch with +`POKEPORT_GBCFX=1`. + ### First run Stock OS has no zenity file picker. Put the `.gb` in `lovegame/`, then press diff --git a/docs/anbernic-rg34xxsp.md b/docs/anbernic-rg34xxsp.md index 8e41d4f5..4081f4bc 100644 --- a/docs/anbernic-rg34xxsp.md +++ b/docs/anbernic-rg34xxsp.md @@ -55,6 +55,16 @@ In-game controls use the normal PortMaster / SDL pad map, rebindable under ## Notes +**GBC FX is off on this device.** The launcher exports `POKEPORT_GBCFX=0`, +which hides the GBC FX row from OPTIONS, pins the level to OFF, and clears a +level carried over in an `options.lua` from another machine. The H700's Mali +GPU is in the same class as the phone GPUs that compile that present pass and +then show a black frame (issue #136), and `love.system.getOS()` reports +`"Linux"` here, so the Android gate would not have caught it. Every other +display option — COLORS, TILT, ZOOM, VOID FILL, MAX FPS — works normally. If +your device turns out to handle the pass, launch with `POKEPORT_GBCFX=1` to +put the row back. + The pack bundles the LÖVE 11.5 aarch64 runtime from [PortMaster](https://portmaster.games/), so the device does not need a separate `love_11.5` runtime download on first launch. The launcher resolves diff --git a/docs/new-features.md b/docs/new-features.md index e07b9805..4ff64e88 100644 --- a/docs/new-features.md +++ b/docs/new-features.md @@ -129,6 +129,14 @@ It runs as a final present pass after world + UI composite in ([github.com/mattakins/Pixel_Transparency](https://github.com/mattakins/Pixel_Transparency)). Default OFF; persisted as `save.options.gbcfx`. +Mobile GPUs often compile the pass but present a black frame, so Android and +iOS hide the row entirely, pin the level to OFF, and rewrite a level already +persisted in `options.lua` (issue #136). `POKEPORT_GBCFX` overrides that +decision either way, same tri-state as `POKEPORT_TOUCH`: `=0` refuses the +effect, `=1` forces it available. The Anbernic handheld pack exports `0` from +its launcher because the device reports `"Linux"` while its GPU is in the +phone class (see [Anbernic RG34XXSP](anbernic-rg34xxsp.md)). + ## Peer-to-peer link play (lua-enet) Trades and link battles connect two copies of the game directly over diff --git a/src/render/GBCFX.lua b/src/render/GBCFX.lua index 0a05db7f..c2788a2a 100644 --- a/src/render/GBCFX.lua +++ b/src/render/GBCFX.lua @@ -25,7 +25,16 @@ local shader -- false = unavailable (headless / no shader support) -- Mobile GPUs often compile this pass but present a black frame, and the -- level persists in options.lua -- soft-bricking the APK until a manual -- edit (issue #136). Desktop is unchanged; Android/iOS refuse the effect. +-- +-- POKEPORT_GBCFX overrides the platform default either way ("1" force on, +-- "0" force off), same tri-state as POKEPORT_TOUCH. Handheld packs whose +-- GPU is in the same class as a phone's but whose getOS() says "Linux" set +-- it to 0 in their launcher (build-rg34xxsp.sh); it also lets a desktop +-- checkout exercise the unsupported path without stubbing love.system. function GBCFX.isSupported() + local env = os.getenv("POKEPORT_GBCFX") + if env == "1" then return true end + if env == "0" then return false end if not love or not love.system or not love.system.getOS then return true end local osName = love.system.getOS() return osName ~= "Android" and osName ~= "iOS" diff --git a/tests/parity_gbcfx.lua b/tests/parity_gbcfx.lua index 996c20ab..891008e6 100644 --- a/tests/parity_gbcfx.lua +++ b/tests/parity_gbcfx.lua @@ -121,5 +121,51 @@ end check(not hasGbc, "Options menu omits GBC FX on Android") love.system = prevSystem +-- POKEPORT_GBCFX overrides the platform default both ways. Handheld packs +-- (build-rg34xxsp.sh) export 0 because their getOS() says "Linux" while the +-- GPU is phone class; 1 is the escape hatch if a device turns out to cope. +local prevEnv = os.getenv("POKEPORT_GBCFX") +local realGetenv = os.getenv +local stubEnv +os.getenv = function(name) + if name == "POKEPORT_GBCFX" then return stubEnv end + return realGetenv(name) +end + +stubEnv = "0" +check(not GBCFX.isSupported(), "POKEPORT_GBCFX=0 refuses GBC FX on desktop") +GBCFX.setLevel(3) +eq(GBCFX.level, 0, "setLevel forces OFF under POKEPORT_GBCFX=0") +local handheldOpts = { gbcfx = 4 } +check(GBCFX.applyOptions(handheldOpts) == true, + "applyOptions reports a cleared level under POKEPORT_GBCFX=0") +eq(handheldOpts.gbcfx, 0, "applyOptions heals a persisted level on a handheld") +check(not GBCFX.active(), "active() is false under POKEPORT_GBCFX=0") + +local omHandheld = OptionsMenu.new({ + data = { rulesets = {}, constants = {} }, + save = { options = {} }, + stack = { pop = function() end }, + input = { wasPressed = function() return false end }, + modStatus = { available = {} }, +}) +hasGbc = false +for _, row in ipairs(omHandheld.rows) do + if row.id == "gbcfx" then hasGbc = true end +end +check(not hasGbc, "Options menu omits GBC FX under POKEPORT_GBCFX=0") + +-- "1" wins over the Android gate, so the override is a real two-way door. +stubEnv = "1" +love.system = { getOS = function() return "Android" end } +check(GBCFX.isSupported(), "POKEPORT_GBCFX=1 forces GBC FX on despite Android") +love.system = prevSystem + +stubEnv = nil +check(GBCFX.isSupported(), "unset POKEPORT_GBCFX falls back to the OS check") +os.getenv = realGetenv +eq(os.getenv("POKEPORT_GBCFX"), prevEnv, "os.getenv restored") +GBCFX.setLevel(0) + -- === summary === S.finish()