5.5 Recording and playback¶
Tapes: fast or real time¶
Tape files (.tap, .tzx) load two ways. Either way LOAD "" is typed in
for you when the tape is attached.
Fast load is the default and is what you want almost always: JNEXT short-circuits the ROM's loading routine and the program appears in seconds.
Real time replays the tape as audio, at the speed of an actual cassette —
several minutes, loading stripes, screeching and all. Use it for authenticity,
or for the occasional program with a custom loader that fast-load cannot
follow. Turn it on with Tape > Fast Load (uncheck it) or --tape-realtime.
There is one fast/real-time setting, the Tape > Fast Load toggle, which
changes it for the session; the setting it starts from is Tape fast-load by default in
Settings > Preferences > Startup. Tape > Open Tape File…, File > Load NEX File…, a .tap
or .tzx given with --load and a tape restored from a snapshot all follow it.
--tape-realtime switches it to real time for that run only, winning over the
saved choice, and is never saved. The SDL build has no menu or saved choice, so
the option is its whole setting.
.wav files are always real time; there is no ROM routine to short-circuit.
Automatic play/stop is on by default. A real tape deck needs a finger on
STOP and PLAY when a program is slow between blocks (many tape conversions run
a BASIC loader in the gaps). JNEXT does it for you: in a silent gap between
two blocks, when no program is reading the tape port, the deck stops; it
plays again, from the start of the next block, as soon as a program reads the
port again. Nothing is cut or repeated, and a program that keeps listening sees
the same tape as before. That is why tapes with slow BASIC loaders load in real
time. It does nothing in fast load. .wav files are never paused. Turn it off
with Tape > Auto Play/Stop, Settings > Preferences, or
--no-tape-auto-play for a deck that runs straight through, like a cassette
without a finger (a TZX "stop the tape if in 48K mode" block stops only on a 48K
machine, as the TZX specification says, whatever this setting is).
Tape > Open Tape File… (Alt+T) loads a tape, fast or in real time as
Tape > Fast Load shows, and Eject Tape and Rewind do what they say (a
.wav rewinds by starting again). The status bar shows the tape name and, while
loading, the block position. A new tape replaces the one that was in, whatever
its format; a file that is not a valid tape is refused with a warning, and the
tape that was in stays in.
Saving to tape¶
Tape > Start Saving… (or --tape-save FILE) sends what the machine saves to
a file, until Tape > Stop Saving (or until JNEXT exits). The file's
extension picks the format:
.tzxrecords the tape output, like a cassette recorder plugged into the MIC jack, so anything a program saves is captured: BASICSAVE, and also games and tools with their own saving routines. Standard blocks are stored as standard TZX blocks, faster or slower ones with their own timings, and anything else as the exact pulses..wavrecords the same signal as sound (8-bit mono, 44100 Hz), for other emulators or for a real Spectrum through an audio cable..tap(or any other name) keeps only what is saved through the ROM's own routine, which is what BASICSAVEuses.
SAVE through the ROM is instant whatever the format: JNEXT takes the block
without making you wait for the routine. Other savers take as long as they take
on a real machine. Saving adds to the end of an existing file, so a session can
fill one tape; a .tzx or .wav that is not of the same kind is refused.
What the tape output carries, the file gets. A program that clicks the MIC line while you play leaves those clicks on the tape, and a tape playing in real time is copied to the output, as on a real Next. Start saving just before the save and stop just after it to keep the file clean.
Ctrl-C in a terminal and kill (SIGTERM) close JNEXT properly: the file is
finished like a close finishes it. If JNEXT is really killed instead (kill -9,
a crash), the file still loads: everything saved up to the last pause is on disk. A .tzx keeps
every block SAVE wrote and every block a program's own saver had finished,
but the pause after the last block may be shorter than it was; a save still in
progress when JNEXT stopped is lost, as it would be on a cassette. A .wav keeps
the sound up to the last change of level.
Video¶
File > Record MPEG4 Video… (Ctrl+F5; ⌃F5 on a Mac) starts recording video with audio to
an MP4; Stop (Ctrl+F6; ⌃F6 on a Mac) ends it. From the command line, --record FILE.
This needs ffmpeg installed and on your PATH — JNEXT feeds it the frames.
If it is missing, --record fails immediately: JNEXT says so and exits
non-zero without emulating anything, rather than running a session you would
find out afterwards had never been recorded.
To capture only the audio, --wav-record FILE writes a standard WAV. It needs
neither ffmpeg nor a sound card, so it works in automated runs.
Leaving JNEXT with a recording still running finishes the file rather than abandoning it — File > Quit, Alt+Q and closing the window all stop and finalise it.
RZX: recording what you did¶
An RZX file records your input rather than the screen, alongside a snapshot of the machine. Replaying it reproduces the session exactly, keystroke for keystroke — a walkthrough, a bug report, or a speedrun that stays honest.
- File > Record RZX…, or
--rzx-record FILE; File > Stop RZX Recording to finish. From the command line the recording starts with the machine — or, when you also--loada program, as soon as it is loaded, so the recording holds it — and the file is written when JNEXT exits. - File > Play RZX Recording…, or
--rzx-play FILE. Opening a.rzxwith File > Load NEX File…, loading it with--load, or naming it as the file to run (jnext session.rzx) plays it too. Every one of these starts the machine afresh, the way loading a program does, so a recording replays the same whichever you use. A file that cannot be played is refused before anything is reset, and the Play RZX item needs the.rzxextension.
The command-line options work the same whichever way you run JNEXT: the normal
window, the SDL-only build, or --headless. A recording that fails to load is
reported, and JNEXT then exits with a non-zero status, exactly as it does for a
program that fails to load. So does a recording that cannot be written: a
--rzx-record file that cannot be created stops JNEXT before the machine
starts, and one that cannot be saved (a full disk) makes it exit non-zero.
In the window, the File menu says so instead: a recording that cannot be started or saved, and a file that cannot be played, each put up a message. Only one recording runs at a time — Record RZX… while one is running tells you to stop it first — and nothing is recorded while a recording plays back.
A reset ends a recording. A hard reset (the Reset button, F1, or the program's own), loading another program, changing the machine type, F4, or starting to play an RZX saves the recording at that point and stops it, with a note on the status bar: a recording replays your input, and a reset is not input, so it could not be replayed. Start a new recording afterwards if you want the rest.
RZX and tape saving do not mix: while saving to tape (--tape-save, or Tape >
Start Saving…), JNEXT refuses to record or play an RZX — from the command line
and from the File menu alike — and while an RZX runs, saving cannot start,
because the SAVE capture skips the ROM routine a recording would have to replay.
While a recording runs, tapes load in real time, at their true speed: a fast load skips the ROM's own loader, and a recording can only replay what the machine actually did.
An RZX made elsewhere that carries more than one snapshot — some emulators add one mid-recording — plays up to the second snapshot, and JNEXT says so.
Because it stores input rather than pixels, an RZX is tiny compared with a video — but it only replays correctly in an emulator that models the machine the same way. It also only replays what its snapshot holds: the memory and the paging of the 48K, 128K, Pentagon or +3. The Next hardware a program on those machines can still reach — on JNEXT as on a real Next — is not in it: the NextREGs, the DMA, and the sprite, palette and Copper memory.
Port reads the DMA makes are input like any other and are recorded and replayed with the program's own; earlier JNEXT versions missed them, so a program that read a port through the DMA replayed out of step. The DMA's settings are still not in the snapshot. A program that set the DMA up before the recording started replays its transfers from a DMA that was never set up, and goes out of step; one that sets it up after the recording starts, or for every transfer, replays faithfully.
Recording is not available on a Next¶
JNEXT records an RZX on a 48K, 128K, Pentagon or +3 only. The Next is JNEXT's default
machine, so recording needs --machine 48k, 128k, pentagon or plus3 — or, in the GUI,
Machine ▸ Machine Type. Ask for a recording on a Next and JNEXT says so
instead of starting one.
The reason is in the format rather than in JNEXT. An RZX holds two things: a snapshot of the machine the recording starts from, and a log of every value the program read from a port. The snapshot has to be one of the classic formats — and none of them can describe a Next, with its extra RAM, its NextREGs, Layer 2, the tilemap, the sprites and the Copper. Worse, the log records the values and not the ports they came from, so the snapshot and the log have to agree exactly on what the program reads and in what order; a snapshot that puts the machine back even slightly differently shifts every value in the log, and nothing in the file can detect it. A Next recording is therefore either missing most of the machine or quietly out of step, and JNEXT will not write one.
Playing one still works. Earlier JNEXT versions did write Next recordings, so those files exist; JNEXT plays them and warns that the replay may not be faithful. A program whose whole state lives in the classic 48K part replays perfectly well — which is exactly why the limitation went unnoticed for so long.
A recording plays on the machine it was recorded on, whatever machine you have
selected: JNEXT writes the machine into every recording it makes, and for one
made elsewhere it reads the machine from the embedded snapshot. Playing it
switches to that machine, and Machine > Machine Type shows it — it stays
selected afterwards, as if you had picked it there. For a recording given on
the command line, an explicit --machine wins over the recording; JNEXT warns
when the two disagree, because the playback then goes out of step. A recording that does not say —
one made by JNEXT 1.0.0 or earlier on a 48K SNA snapshot, or one of a machine
JNEXT does not emulate — plays on the machine you have selected.
Every option mentioned in this chapter, and the ones that are not, are listed
in full in the manual page — man jnext, or USAGE.md.