We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

BEAT

From Esolang
Jump to navigation Jump to search

BEAT is a music-oriented esoteric programming language whose complete interpreter runs from a 1.44 MB floppy disk image in 16-bit real mode. It does not run on top of an operating system: the boot sector loads the BEAT engine, and the engine drives the machine's internal speaker through the 8253 timer and port 61h.

Program format

A BEAT program is a byte string stored in sector 4 of the disk image. The program is limited to 511 bytes followed by a NUL terminator. The engine starts at 0x0600; the program is independent from the engine sectors, so the music can be changed without rebuilding the interpreter.

The reference source contains nine catalogue programs. The first program is a scale:

T4D9N440.N494.N523.N587.N659.N698.N784.H

Disk layout

Sector Address Content
1 0x000 FAT12-compatible boot sector and loader
2-3 0x200 BEAT engine, loaded at 0x0100
4 0x400 User program, up to 511 bytes plus NUL

At runtime the engine uses the following memory areas:

Address Purpose
0x0000-0x04FF IVT and BIOS Data Area; untouched by the engine
0x0100 Loaded BEAT engine
0x0500 Instruction pointer, register, tempo, duration and tape pointer
0x0600 Program loaded from sector 4
0x0800 2 KB runtime tape

Execution model

The machine has one 16-bit register and a 2 KB tape. Arithmetic instructions operate on the register. R and W connect the register to the tape, allowing a value to be stored and later reused as a note frequency or loop state.

The speaker is driven by the 8253 programmable interval timer. Requested frequencies are converted to integer timer divisors, so the physical output is the frequency the hardware can express rather than necessarily the requested frequency. Durations use BIOS ticks at approximately 18.2065 Hz.

Instructions

Instruction Effect
>, < Move the tape pointer
+, - Increment or decrement the register
. Play the register as a frequency
, Keyboard input; the reference no-console path reads zero
[, ] Loop while the register is non-zero
T<n> Select tempo table entry 0-9
D<n> Set note duration 0-9
N<hz> Load a decimal frequency, for example N440
P Pause for the current duration
R Read the tape cell into the register
W Write the low byte of the register to the tape
J Unconditional absolute jump
Z Jump if the register is zero
S Toggle the speaker state and sustain the last timer tone
H Stop the machine

The Brainfuck-like loop instructions are register loops, not ordinary multi-cell Brainfuck loops. The tape stores only the low byte of a register value, from 0 through 255.

J and Z use absolute addresses based on the program's fixed load address. Programs using them are therefore not generally relocatable inside the sector.

I/O and output

BEAT has no conventional text stdout. Its observable output is the sound produced by the internal speaker. A run can be observed through:

  • the physical or emulated speaker;
  • the reference simulator's list of frequency-duration events;
  • a rendered WAV file;
  • QEMU audio capture and note analysis.

Building and running

The image is built from BEAT.asm with NASM:

./build.sh
qemu-system-i386 -fda BEAT.img

The reference simulator can run a program without booting QEMU:

python tools/beat_sim.py 'T4D9N440.N494.N523.H' scale.wav

The simulator is a semantic reference, not the final hardware test. The hardware-facing verification is:

python tools/test_qemu.py

Changing a program without rebuilding

The program occupies its own sector. A replacement program can be patched into an existing image:

python tools/patch_sector4.py BEAT.img program.beat output.img
qemu-system-i386 -fda output.img

The patcher preserves the boot signature and rejects programs larger than the sector budget.

FLOW integration

tools/flow2beat.py is an adapter from a FLOW execution trace to a BEAT program. It maps particle positions to pitches, particle density to tempo, state changes to tape operations, and particle deaths to pauses. This is an output adapter, not a claim that BEAT and FLOW share the same execution semantics.

python tools/flow2beat.py execution.trace.json -o flow.beat
python tools/patch_sector4.py BEAT.img flow.beat BEAT_FLOW.img
qemu-system-i386 -fda BEAT_FLOW.img

The generated program is still subject to the 511-byte sector limit. Events that do not fit are not encoded in the output program.

Computational status

BEAT is a Bounded-storage machine.

Implementation

The reference implementation is in BEAT and is released under the MIT license. The simulator and analysis tools live in tools/; they verify behavior but are not part of the disk image build chain.