# Crash BASIC 1.35.0 Release Notes

*~written by Crash-tan~*

## THE BAKE-IT-ONCE RELEASE

There's a new block in town: **`BEGIN MEMORYBUFFER` … `END MEMORYBUFFER`**.
Draw a pile of primitives inside it — `PSET`, `LINE`, `CIRCLE`, `POLYGON`,
`CLS` — and instead of each one taking the slow road to the screen, the whole
batch gets rasterized **once** into a single texture you can reuse forever.

If you've ever written a loop that `PSET`s a few thousand pixels and felt it
drag, this is for you. That loop used to be a few thousand individual trips to
the renderer. Now it's one.

```basic
SCREEN 1, 320, 240

BEGIN MEMORYBUFFER "stars"
  FOR i = 1 TO 500
    PSET (RND * 320, RND * 240), 15
  NEXT
END MEMORYBUFFER

' "stars" is now a texture. Slap it down as many times as you like.
PUTIMAGE (0, 0), "stars"
```

---

## Why it's fast

Every `PSET` / `LINE` / `CIRCLE` you draw normally is its own little command
that travels to the renderer and gets drawn right then. Great for a handful of
shapes. Death by a thousand cuts when you're generating a whole texture pixel
by pixel — especially in the browser, where each command crosses a worker
boundary.

`MEMORYBUFFER` flips it around. Inside the block, your primitives are **recorded**,
not drawn. At `END`, the entire batch ships as a *single* operation, gets
rasterized into one RGBA texture, and is uploaded to the GPU exactly once. One
trip instead of N. The more primitives you were drawing, the bigger the win.

The result is a normal texture — hand it to `SET SPRITE`, `PUTIMAGE`, particles,
anything that takes an image name.

---

## How to use it

```basic
BEGIN MEMORYBUFFER "name"             ' size = current SCREEN resolution
BEGIN MEMORYBUFFER "name", 32, 32     ' or pick an exact size
```

The name is the texture you're building. Leave off the size and the buffer
matches your current `SCREEN` (so a `SCREEN` has to be active); pass `width,
height` for something specific. Buffers go up to 8192×8192.

The buffer starts **fully transparent**. Draws layer on top of each other in
the order you make them, exactly like drawing to the screen — so later shapes
cover earlier ones. `CLS` inside the block fills the whole buffer (`CLS 0` for
black, plain `CLS` for transparent).

```basic
BEGIN MEMORYBUFFER "coin", 16, 16
  CLS                                 ' transparent canvas
  CIRCLE (8, 8), 7, 14, 6             ' gold rim, filled
  CIRCLE (8, 8), 4, 14               ' inner ring
END MEMORYBUFFER

ENABLE SPRITE 0
SET SPRITE 0, 100, 100, "coin"
```

You can use real control flow in there, too — that's the whole point of
generating textures procedurally:

```basic
BEGIN MEMORYBUFFER "grid", 256, 256
  FOR x = 0 TO 256 STEP 16
    LINE (x, 0)-(x, 256), 8
    LINE (0, x)-(256, x), 8
  NEXT
END MEMORYBUFFER
```

---

## What's allowed inside (and what isn't)

A `MEMORYBUFFER` block is for **primitive rasterization only**. That keeps it
fast, predictable, and identical on every platform. So:

**Allowed:** `PSET`, `PRESET`, `LINE`, `CIRCLE`, `POLYGON`, `CLS`, plus all the
control flow you'd expect (`IF`, `FOR`, `WHILE`, `DO`), variable assignment, and
calls to your own `SUB`s/`FUNCTION`s (a helper that only draws primitives
composes just fine).

**Not allowed:** sprites, `PRINT`, `PUTIMAGE`, resource loads (`LOADIMG` and
friends), `SETIMAGE`, `BEGIN FRAME`, `SCREEN`, audio, and nesting another
`BEGIN MEMORYBUFFER`. Try one and you get a **loud, located error** telling you
exactly what wasn't allowed — no silent weirdness.

### Textured polygons stay on the GPU

A `POLYGON` with a texture argument is **intentionally** off-limits inside a
buffer. Texture sampling is a GPU job and always will be — it has no place in a
CPU-rasterized buffer. Solid-color and filled polygons are welcome here; if you
want a *textured* polygon, draw it straight to a layer or the screen, where the
GPU does the work.

---

## Multiplayer

`MEMORYBUFFER` is a **computed resource**, just like `TEXTTOIMAGE`. It runs on
every interpreter and registers its texture everywhere, but it is **not**
broadcast over the wire — no per-pixel bandwidth. Build it on each client the
same way you build other resources:

```basic
IF ME.ISCLIENT THEN
  BEGIN MEMORYBUFFER "hud", 320, 48
    LINE (0, 0)-(319, 0), 7
    ' ...
  END MEMORYBUFFER
END IF
```

Because the rasterization is plain deterministic CPU math, every client builds
**byte-identical** pixels. No drift, no sync needed.

---

## Compatibility notes

- **Purely additive.** One new block keyword; nothing existing changed. Your
  `PSET` / `LINE` / `CIRCLE` calls behave exactly as before outside a buffer.
- **Same picture everywhere.** The buffer is CPU-rasterized with deterministic
  integer math — identical results on Mac, Windows, Linux, iOS, Android, and the
  browser.
- **Wire-compatible.** The new command rides the existing protobuf transport;
  no breaking protocol or multiplayer changes.

---

*Draw it once. Stamp it forever.*

*— Crash-tan*
