diff --git a/docs/06-graphics.md b/docs/06-graphics.md index 2cd93c1..723b299 100644 --- a/docs/06-graphics.md +++ b/docs/06-graphics.md @@ -244,3 +244,11 @@ The graphics verbs draw straight to the renderer rather than into a display list anything drawn is overwritten by the text layer on the next frame. A program that wants its drawing to persist has to redraw it. This is recorded as a defect rather than a design; see Chapter 13. + +**A redraw also has to fit inside one batch.** The host runs a fixed number of source +lines and then presents, and presenting throws the drawing buffer away — so a run of +drawing verbs longer than one batch is torn rather than merely transient, and an +`SSHAPE` at the end of it captures only the part issued since the present. Watching +`TI#` change is how a program finds the boundary; Chapter 13 has the measured numbers and +[Chapter 18](18-tutorial-breakout-artwork.md#step-4-find-the-frame-boundary) has a +routine that uses them. diff --git a/docs/14-architecture.md b/docs/14-architecture.md index 6535570..2a18c7a 100644 --- a/docs/14-architecture.md +++ b/docs/14-architecture.md @@ -168,8 +168,22 @@ resume there. `akbasic_runtime_run(rt, n)` is `step()` in a `while` with a budget: at most `n` steps, then return regardless. That bound is the only thing standing between a script containing `10 GOTO 10` and your frame rate. `n <= 0` means unbounded, which is right for a test and -wrong for a game. The SDL frontend uses 256; the stdio driver uses 1, because it wants to -refresh the clock between steps. +wrong for a game. The SDL frontend uses 256 (`AKBASIC_FRONTEND_STEPS_PER_FRAME`); the +stdio driver uses 1, because it wants to refresh the clock between steps. + +**That budget is visible to a script, and drawing is where it shows.** The frontend +presents the frame when `run()` comes back, and presenting discards the drawing buffer — +so a sequence of drawing verbs longer than one budget is cut in half by the present in +the middle of it, and an `SSHAPE` afterwards captures only what was issued since. Not a +transient artefact: a torn capture, over whatever the frame before left behind. + +A script cannot read the budget, but it can *see* it: `akbasic_runtime_settime()` is +called once per frame by the host, so `TI#` changes on the first step of a batch and +nowhere else. Spinning until it changes is the only frame synchronisation this dialect +has, and it is what +[Chapter 18](18-tutorial-breakout-artwork.md#step-4-find-the-frame-boundary) is built on. +A host that gives the interpreter a larger budget makes more drawing fit; one that never +calls `settime()` takes the synchronisation away entirely. Time comes in from outside. `akbasic_runtime_settime(rt, ms)` is how the interpreter learns what time it is; it reads no clock, because it owns no loop and must not block. A