ludic/runtime/native
Orkuncakilkaya be74b4de6f feat(bundle): ship a game as a macOS .app, with a splash it controls
`ludic build` produces a program. Double-clicked it opens a Terminal window, it
wears the generic executable icon, it calls itself whatever the file is called,
and it carries none of its assets. `ludic bundle` produces an application.

Everything it needs is in package.ludic, so the command takes no arguments: an
Info.plist and PkgInfo from `app` lines, an .icns built by sips and iconutil at
all ten sizes macOS asks for from a single source PNG, the asset pack in
Contents/Resources, and an ad-hoc signature - which is not optional on Apple
silicon, where an unsigned binary is killed rather than warned about. The bundle
identifier falls back to the package path reversed, so a project that never
thinks about it still gets a defensible one instead of two apps sharing a key
Launch Services hangs the Dock, saved state and permissions off.

A bundled game is moved to ~/Library/Application Support/<name> before main,
because Finder starts a .app with its working directory at "/" where no save
could ever be written. Reads come out of the pack, writes land somewhere real
and per-user, and the game's save code needs no change and no platform
knowledge.

The splash is the other half of looking like an application. A game that loads
165 MB spends a visible moment doing it with nothing on screen, which from the
outside is indistinguishable from a launch that failed. splash_show puts a
borderless window up from the same constructor that mounts the pack - before
main, so it appears while the process is still starting rather than after the
slow part it exists to cover - and reads the artwork out of the pack like any
other asset. It turns the run loop enough times to be mapped and composited
there and then; once composited the backing store survives a busy main thread,
so it stays up for the whole load.

Nothing hides it automatically. Only the game knows when its first real frame is
ready, and a splash that vanishes before that leaves the same black gap it was
covering, so the game calls App.splash_hide(). Headless there is no splash and
the call lowers to nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 16:57:27 +03:00
..
atlas.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
audio.ll feat(audio): Audio.* standard library over a native AVAudioPlayer backend (#22) 2026-08-31 17:52:31 +03:00
audio.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
base64.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
bignum.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
cocoa.ll feat(bundle): ship a game as a macOS .app, with a splash it controls 2026-09-10 16:57:27 +03:00
core.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
dict.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
fx.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
gl.ll feat(gl): OpenGL 4.1 and the ludic.render3d renderer 2026-09-10 03:31:12 +03:00
gl.ludic feat(gl): OpenGL 4.1 and the ludic.render3d renderer 2026-09-10 03:31:12 +03:00
gl_api.ludic feat(gl): OpenGL 4.1 and the ludic.render3d renderer 2026-09-10 03:31:12 +03:00
gl_thunks.ll feat(gl): OpenGL 4.1 and the ludic.render3d renderer 2026-09-10 03:31:12 +03:00
grid.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
http.ll feat(http): Http.* poll-based HTTP/HTTPS client over a native NSURLConnection backend (#6) 2026-08-31 18:10:53 +03:00
http.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
image.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
inflate.ludic feat(gl): OpenGL 4.1 and the ludic.render3d renderer 2026-09-10 03:31:12 +03:00
input.ludic feat(gl): OpenGL 4.1 and the ludic.render3d renderer 2026-09-10 03:31:12 +03:00
jobs.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
light.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
numeric.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
query.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
reflect_io.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
regex.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
regex_vm.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
systems.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
systems_bounds.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
systems_light.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
systems_move.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
systems_sprite.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
systems_tileskin.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
tiled.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
tiled_spawn.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
truetype.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
truetype_raster.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
tween.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
ui.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
ui_draw.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
value.ludic feat(gl): OpenGL 4.1 and the ludic.render3d renderer 2026-09-10 03:31:12 +03:00
xml.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
zstd.ludic refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00