Two things, the second of which is the reason the first is safe.
A NEW KIND. pickFile("stadium") opens the document picker for a Nintendo 64
cartridge and lands it as picked_stadium.z64. The caller I wrote it for is
the Dramatic Shape voxel mod, which builds Pokemon Stadium battle models out
of the player's own cartridge -- on desktop it opens a dialog for that, and
on iOS it could only print a sandbox path to a screen and ask the player to
put a file somewhere they cannot reach from a phone.
Its own filename, not picked_rom.gb, because that is the name the Game Boy
importer watches: a 32 MB N64 ROM landing there is deleted and then reported
to the player as a broken cartridge.
WHICH IS ALSO WHAT AN UNKNOWN KIND USED TO DO. The switch's default case
treated anything it did not recognise as a Game Boy ROM, so a caller asking
for a kind the build predates lost the player's file -- the worst available
answer to "I have not heard of that one". Unknown kinds are refused now.
That refusal is invisible on its own: pickFile returns false, which is also
what "the picker would not open" returns, and a mod cannot tell them apart.
So the host says what it knows -- love.system.pickFileKinds() returns
"rom,mod,sav,stadium", or nil where there is no bridge. A caller asks first
and keeps whatever fallback it had; the voxel mod shows its folder note
again, which is what it did before any picker existed.
Tested on an iPhone 17 Pro: a Stadium cartridge imports from the picker and
the models build.
iOS build (LÖVE 12.0)
Native ROM/mod/save import. The iOS build ships a Swift document-picker bridge (
native/GRPickerBridge.swift+GRBootstrap.m) thatpatch_love_src.pywires into the LÖVE tree on every build:
love.system.pickFile("rom"|"mod"|"sav")andlove.system.createFileare exposed to Lua on iOS (same contract as love-android's SAF picker: picks land in the save dir aspicked_rom.gb/picked_mod.zip/picked_save.sav; exports signal viaexport_done.flag).- The Info.plist overlay enables
UIFileSharingEnabled+LSSupportsOpeningDocumentsInPlace, andGRBootstrap.msweeps.gb/.gbc/.zip/.savfiles dropped in Documents (Files app / Finder) into the LÖVE save dir on every activation — drop a ROM, open the app, and it imports with no taps.src/import/RomImporter.luatreats iOS as a mobile platform and polls for picker results (iOS pickers are in-process modals, so Android's refocus rescan never fires).The note below about a missing "UIDocumentPicker handoff" is resolved by this bridge.
macOS + Xcode only. Fetches the LÖVE 12.0 source tree and matching Apple
dependencies from the official LÖVE source
and Apple dependencies
repositories. conf.lua declares LÖVE 12.0 on iOS and 11.5 elsewhere.
Pin file: LOVE_VERSION → 12.0.
Quick start (simulator)
# Fetch LÖVE 12.0 iOS sources and dependencies (once) + build for Simulator
scripts/build_ios.sh --fetch
The embedded game.love contains no ROM or generated game data. The current
first-boot importer has desktop file pickers only, so a production iOS release
still needs a UIDocumentPicker handoff that passes the selected ROM to LÖVE.
Default output: an unsigned Simulator .app under mobile/ios/build/
(no Apple Developer account required). A convenience copy also lands under
dist/ios/<Config>-<sdk>/.
Install on a booted simulator (example):
xcrun simctl install booted mobile/ios/build/Build/Products/Debug-iphonesimulator/PokemonRed.app
xcrun simctl launch booted com.theboisclub.pokemonred
Or open mobile/ios/love-src/platform/xcode/love.xcodeproj in Xcode,
select the love-ios target, and Run on a Simulator after
scripts/build_ios.sh --package-only (or a full build) has placed game.love.
Device / Release
scripts/build_ios.sh --device # Debug, physical device SDK
scripts/build_ios.sh --device --release # Release configuration
Device builds need a signing identity and provisioning profile configured in
Xcode (or via DEVELOPMENT_TEAM / CODE_SIGN_IDENTITY env vars). This repo
does not store certificates, profiles, or App Store Connect secrets.
Manual out-of-band steps:
- Apple Developer account + App ID for
com.theboisclub.pokemonred - Development or Distribution certificate + provisioning profile
- In Xcode: open
love.xcodeproj→ targetlove-ios→ Signing & Capabilities → select your Team (or setDEVELOPMENT_TEAM=XXXXXXXXXXwhen invokingscripts/build_ios.sh --device) - Archive / export an
.ipafrom Xcode Organizer for TestFlight / Ad Hoc
Layout
| Path | Role |
|---|---|
LOVE_VERSION |
Engine pin (12.0) |
overlays/love-ios.plist |
Portrait-only Info.plist + display name Pokemon Red (copied over the upstream plist every build) |
love-src/ |
Downloaded LÖVE 12.0 source tree (gitignored, do not commit) |
cache/ |
Temporary source and dependency checkout data (gitignored) |
build/ |
xcodebuild derived data (gitignored) |
Game payload lands at:
love-src/platform/xcode/ios/resources/game.love
and is fused into the built .app (LÖVE auto-runs any bundled *.love).
Apple libraries dependency
scripts/build_ios.sh --fetch retrieves the matching iOS libraries and the
SDL3 framework from
love-apple-dependencies.
Re-run it if either dependency directory is absent.
App identity
| Field | Value |
|---|---|
| Display name | Pokemon Red |
PRODUCT_NAME |
PokemonRed |
| Bundle ID | com.theboisclub.pokemonred |
| Orientations | Portrait only (UIInterfaceOrientationPortrait) |
Overrides are applied by the build script (xcodebuild settings + plist overlay)
so refreshing love-src/ does not lose branding.
Flags (scripts/build_ios.sh)
| Flag | Meaning |
|---|---|
| (default) | Simulator, Debug, no signing |
--fetch |
Fetch the LÖVE 12.0 source tree and Apple dependencies if love-src/ is missing |
--device |
Build against iphoneos instead of iphonesimulator |
--release |
Release configuration instead of Debug |
--package-only |
Zip game.love + apply plist overlay; skip xcodebuild |
Also: scripts/build.sh ios delegates here (--release is forwarded).
Preconditions
- macOS (Darwin) with Xcode +
xcodebuildonPATH - iOS platform installed in Xcode (Settings → Platforms).
xcodebuild -showsdksshould listiphonesimulator/iphoneos. A partial install can fail IB/xib compiles withiOS … Platform Not Installedeven when the SDK name appears. love-src/present (--fetch)- iOS libraries under
love-src/platform/xcode/ios/libraries/and SDL3 underlove-src/platform/xcode/shared/Frameworks/