# Crash BASIC 1.42.0 Release Notes

*~written by Crash-tan~*

## THE "SHIP IT EVERYWHERE" UPDATE

This one's about getting your game *out the door* — onto every desktop, from
whatever machine you happen to be sitting at.

Here's the headline I'm genuinely proud of: **you can now build your game for
Windows, macOS, and Linux from a single computer — no matter which of those
you're running.** On a Mac? Hand someone a Windows build. On a Windows PC?
Produce a real macOS app. One machine, all three desktops. And the first time
you target a platform you don't have the build tools for, I'll go fetch them
myself so you don't have to.

---

## Build for every desktop, from any desktop

Packaging used to mean "build for the platform you're standing on." Not anymore.
Point me at your game and pick your targets — in the Package screen, just tick
Windows, macOS, and Linux no matter what you're running, or from the command
line:

```
crashplayer package mygame.crashcart --platform windows,macos,linux
```

You get a ready-to-run build for each: a Windows folder, a macOS `.app`, a Linux
folder — all from the one computer. The first time you target a platform whose
build tools aren't installed yet, I'll offer to grab them and then carry right
on. No compiler scavenger hunt.

### Building a Mac app on Windows? A few finishing touches on the Mac

Some things only a Mac can do, so if you build the macOS `.app` **on Windows**,
the first time it lands on a Mac you (or whoever you send it to) finish it
there — just once:

```bash
# Windows can't set the Unix "executable" bit, so turn it on:
chmod +x YourGame.app/Contents/MacOS/YourGame

# Clear the "downloaded from the internet" quarantine flag macOS adds:
xattr -dr com.apple.quarantine YourGame.app

# And give it a signature — a build made off a Mac comes out unsigned:
codesign --force --deep --sign - YourGame.app
```

Then it launches. (Built it on a Mac in the first place? None of this applies —
it's all handled for you.) And whenever a build comes out unsigned, I'll tell
you plainly rather than pretend otherwise.

---

## Lighter on its feet

Under the hood I went on a bit of a diet. CrashPlayer — and the games you
package — used to carry a couple of separate media libraries around for sound
and video. Those are **built right in now**: no loose files riding shotgun next
to your game, nothing to misplace, and one less thing to go wrong on someone
else's computer. Sound and video work exactly as before — the bundle's just
tidier and more self-contained. (Which is the whole point.)

---

## JMES() — reach into your data in one line

Got a chunk of JSON-shaped data — a config, a save file, a roster, an API
response — and you need *one thing* out of deep inside it? **`JMES(data,
"query")`** runs a [JMESPath](https://jmespath.org) query and hands you back the
answer as a normal Crash value:

```basic
data = DESERIALIZE$(json$)

' Reach a nested field
PRINT JMES(data, "players[0].name")

' Run a function over an array
best = JMES(roster, "max(players[*].score)")

' Filter, then take the first match
winner$ = JMES(roster, "players[?score > `100`].name | [0]")
```

Objects come back as objects, arrays as arrays, numbers and strings as
themselves, and a query that matches nothing gives you `0` — the same convention
as `DESERIALIZE$`. No more hand-walking a nested tree to fish out a single value.
(A bad query stops loudly and tells you, rather than guessing.)

---

## SET SPRITE ... FRAME — flip a frame, nothing else

Animating a sprite by hand? You no longer have to re-state its position and image
just to change which spritesheet cell it's showing. **`SET SPRITE n FRAME f`**
changes the frame all on its own:

```basic
SET SPRITE 0 FRAME 2                  ' just switch to cell 2

SET SPRITE 0, x, y, "hero" FRAME 3    ' ...or set the frame while you place it
```

Frames are 0-based. This is purely a tidier way to nudge one frame — your
existing `SET SPRITE n, x, y, img, frame` calls parse exactly as they always did.

---

## Fixes

- **Packaged games launch reliably however they're started.** A double-clicked
  or app-launched build could quit partway through play depending on where the
  system happened to start it from. It now sets up its own workspace on launch,
  so it behaves the same whether you run it from a terminal or double-click the
  icon.
- **Friendlier cloud-save messages on iOS** when you run into iCloud's storage
  limits, plus a guard against oversized carts — clear words instead of a
  mystery failure.

---

## Compatibility

Nothing here changes a line of the code you've already written.

- `JMES` and `SET SPRITE ... FRAME` are brand-new — they don't touch anything
  existing, and the familiar `SET SPRITE n, x, y, img, frame` still parses just
  as before.
- The packaging changes are about *building* your game, not about the language —
  your `.crashcart` is unchanged.
