feat(pack): asset packs, so a built game is a thing you can hand someone
A Ludic game opened its assets by a path relative to the working directory, so `build/mygame` ran only from the project root and there was nothing to give anyone but "the binary, and also this whole tree". A game is not one file, but shipping it has to be. `ludic pack` writes a .lpak: a header, a name-sorted entry table, a name heap and the blobs, 16-byte aligned. Entries are stored rather than compressed - PNG, JPEG and glTF binary arrive compressed already, and a decompressor on the load path would spend CPU to make the file no smaller. The reader is spliced into the compiler at the one place every asset in a Ludic program comes through: file_open. gltf_load, tex_load, Audio.load, Fs.read_text and the renderer's own shader loads all bottom out there, so routing it through @lp_pak_open reaches every one of them without any of them knowing. A read of a packed path becomes an fmemopen over the mapped bytes; everything else is the fopen it always was. Fs.exists and Fs.size consult the packs too, so a game that guards a load with Fs.exists keeps finding its assets once they are packed. The pack is mmap'd rather than read: 165 MB of textures costs one syscall at boot and pages in only what is touched. @lp_pak_boot runs from @llvm.global_ctors, before main, so a pack is mounted before the game's first line - and it reads packs.index, a plain list, so the mount order is explicit and a later pack shadows an earlier one. Without a packs.index nothing mounts and every open goes to the filesystem exactly as before, which is every `ludic run` during development. Packing is a shipping step and is invisible until you ship. The compiler reproduces itself byte-exactly and the C-free bootstrap from the seed still holds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9ba093bf07
commit
ce5bf0fe0e
11 changed files with 14901 additions and 13587 deletions
|
|
@ -25,6 +25,7 @@ program Ludic {
|
|||
import "project.ludic"
|
||||
import "pkg.ludic"
|
||||
import "assets.ludic"
|
||||
import "pack.ludic"
|
||||
|
||||
function usage() -> void {
|
||||
print("ludic — the toolchain for the Ludic language")
|
||||
|
|
@ -49,6 +50,11 @@ program Ludic {
|
|||
print(" build-lib <module.ludic> compile a package's module to a prebuilt dylib in lib/<target>/")
|
||||
print(" link-flags print the clang flags to link this project's prebuilt module dylibs")
|
||||
print("")
|
||||
print("shipping:")
|
||||
print(" pack [--out FILE] [dirs...] pack the assets into build/<name>.lpak")
|
||||
print(" pack --list FILE print what is in a pack")
|
||||
print(" pack --verify FILE re-hash every entry against the table")
|
||||
print("")
|
||||
print("the toolchain:")
|
||||
print(" version print the toolchain version")
|
||||
print(" upgrade [version] reinstall from the docs site (the same script that installed it)")
|
||||
|
|
@ -88,6 +94,7 @@ program Ludic {
|
|||
if (cmd == "verify") { return cmd_pkg_verify() }
|
||||
if (cmd == "vendor") { return cmd_pkg_vendor() }
|
||||
if (cmd == "assets") { return cmd_fetch_assets() }
|
||||
if (cmd == "pack") { return cmd_pack() }
|
||||
if (cmd == "build-lib") { return cmd_pkg_build_lib() }
|
||||
if (cmd == "link-flags") { return cmd_pkg_link_flags() }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue