NAUG Ch9 — Buffers

Holmes & Dickens, The New Advanced User Guide, pp.143-153. The buffer layer is FIFO queues between producers (keyboard scan, OSWRCH, SOUND command) and consumers (input reader, printer driver, sound chip). All operate at the IRQ layer so the foreground task doesn’t block waiting for slow peripherals.

Buffer IDs

IDBufferDefault size
0Keyboard inputtypically 32 bytes
1RS423 inputtypically 32 bytes
2RS423 outputtypically 32 bytes
3Printertypically 64 bytes (&40)
4SOUND channel 0typically 16 bytes
5SOUND channel 1typically 16 bytes
6SOUND channel 2typically 16 bytes
7SOUND channel 3typically 16 bytes
8Speech(only used if speech hardware fitted)

Memory for all buffers is reserved on every machine, even where the hardware isn’t present. Buffer storage lives at &800-&9BF and around (os-workspace).

Vectors

VectorAddressPurpose
INSV&22A/&22BInsert byte into buffer
REMV&22C/&22DRemove (or examine) next byte
CNPV&22E/&22FCount free / used space, or purge

No ID validation — passing an out-of-range buffer ID has undefined behaviour. Not available across Tube — vector hooks must reside on the I/O processor (ideally in a service ROM).

INSV — insert into buffer

Entry: A = value, X = buffer ID. Exit: A, X preserved. Y undefined. C=1 if buffer full, C=0 if inserted.

REMV — remove or examine

Entry: X = buffer ID. V flag selects mode: V=1 examine (don’t remove), V=0 remove.

Exit:

  • Remove (V=0): Y = byte just removed, A undefined, X preserved.
  • Examine (V=1): A = next byte without removing, Y undefined, X preserved.
  • C=1 if buffer was empty.

CNPV — count or purge

Entry: X = buffer ID. V=1 purge / V=0 count. For count: C=1 means “return free space”, C=0 means “return content length”.

Exit: X (low) + Y (high) form the 16-bit count. (For a purge, X/Y are preserved.)

OSBYTE wrappers

OSBYTEFunctionNotes
&0F (15)Flush buffer classX=0 all, X≠0 input buffers only
&15 (21)Flush specific bufferX = buffer number (0-8)
&80 (128)Read buffer statusX = 0xFF-id (e.g. &FF for keyboard, &FC for printer). Returns count in X.
&8A (138)Insert byteX = buffer, Y = value. C=1 if full.
&91 (145)Get byteX = buffer. Y = byte. C=1 if empty.
&98 (152)Examine next byteSame as REMV examine. OS 1.20 and earlier: Y is a pointer indexed off &FA/&FB zp; later OS: Y is the byte itself.
&99 (153)Insert into input bufferX = 0 (keyboard) or 1 (RS423); Y = char. Generates input event 2.

OSBYTE &80 uses the inverted buffer ID (&FF = id 0, &FE = id 1, etc.) — collision with ADC channel read, where X has the channel number. osbyte has the mapping.

Notes for buffer-vector hooking

Several caveats from NAUG §9.4 p137-139:

  • No ID validation in the OS routines — your custom INSV/REMV/CNPV handler should check X before claiming.
  • Hooks must live in the I/O processor (Tube limitation).
  • The right place for hooks is a service ROM — sideways RAM or EPROM. Otherwise BASIC will trample the handler code (the NAUG example explicitly warns about this).
  • OS calls that touch buffers (OSBYTE, OSWRCH, OSWORD &00, etc.) implicitly go through these vectors — your hook applies everywhere.

Filed into

  • buffers — Buffer reference + vector hook patterns.
  • Updates: osbyte entries &0F/&15/&80/&8A/&91/&98/&99 now point here.
  • Updates: os-workspace cross-links — buffer RAM at &800-&9BF.

Open follow-ups

  • Sound buffer mechanics: how the SOUND OSWORD enqueues into channel 0-3 buffers and how the 100 Hz IRQ services them — covered in Ch21 ingest.
  • Exact per-buffer base addresses and lengths — NAUG p114 has the page-1 sound layout; full table would need to dump zp &E2-&E6-ish for CFS state and the OS workspace buffer pointers at &2C3-&2D4 (Master) / &2CC-&2DD (Model B).

This wiki is curated by Claude following the LLM-Wiki methodology — a human curates source documents, the LLM compiles structured cross-linked markdown. Content may contain errors, omissions, or stale claims. For authoritative information refer to the original source documents in the bbc-documents GitHub archive.