7. Output streams and file handling

7.1

At any given time text is being output through a selection of
"output streams" (possibly none, possibly several at once).

7.1.1

Two output streams are common to all Versions:
number 1 (the screen) and 2 (the game transcript, usually printed
to a printer or a file).

7.1.1.1

In Versions 1 to 5, the player's input to the read
opcode should be echoed to output streams 1 and 2 (if stream 2
is active), so that text typed in appears in any transcript.
In Version 6 input should be sent only to stream 1 and it is
the game's responsibility to write to the transcript.

7.1.1.2

In Infocom's Version 4 game 'A Mind Forever Voyaging',
which anticipated a printer rather than a file to receive the
transcript, stream 2 is turned off and on again several times in
quick succession. Thus if an interpreter decides where to send
the transcript by asking the player for a filename, this question
should only be asked once per game session, not every time stream
2 is selected.

7.1.2

Versions 3 and later supply these and two other output streams,
numbered 3 (Z-machine memory) and 4 (a script file of the player's whole
commands and of individual keypresses as read by read_char).

7.1.2.1

Output stream 3 writes to a table in dynamic memory. When the
stream is selected, the table may have any contents (even the initial 'size'
word will be ignored by the interpreter). While the stream is selected, the
table's contents are unspecified (and a game cannot safely read or write
to it). When the stream is deselected, the initial word of the table holds
the number of characters printed and subsequent bytes hold those characters.
Similarly, in Version 6, the total width of printing (in units) will then be
stored in the word at $30 in the header. (It is the programmer's
responsibility to make the table large enough: the interpreter performs no
overflow checking.)

7.1.2.1.1

*** It is possible for stream 3 to be selected while
it is already on. If this happens, the previous table address is
remembered and the previous table is resumed when the new one is
finished. This nesting can reach a depth of up to 16: if stream 3
is opened for a seventeenth time, the interpreter should halt with
an error message.

7.1.2.2

Output stream 3 is unusual in that, while it is selected, no
text is sent to any other output streams which are selected. (However,
they remain selected.)

7.1.2.2.1

Newlines are written to output stream 3 as ZSCII 13. (A game
should never print_char the value 10, or any other value which is
undefined as a ZSCII output code.)

7.1.2.3

Output stream 4 is unusual in that, when it is selected,
the only text printed to it is that of the player's commands and
keypresses (as read by read_char). (Each command is written, in
one go, when it has been finished. Time delays and mouse-clicks should ideally
be recorded. For suggestions on how this might be achieved, see the remarks section
below. Mistypes and uses of 'delete' are not written.)

7.2

On output streams 1 and 2 (only), text printing may be "buffered"
in that new-lines are automatically printed to ensure that no word
(of length less than the width of the screen) spreads across two lines
(if the interpreter is able to control this).
(This process is sometimes called "word-wrapping".)

7.2.1

In Versions 1 to 3, buffering is always on. In Versions 4
and later it is on by default (at the start of a game) and a game can
switch it on or off using the buffer_mode opcode.

7.2.2

In Version 6, each of the eight windows has its own "buffering
flag". In Versions 3 to 5, the buffer_mode applies only to the lower
window, and buffering never happens in the upper window.

7.3

In Versions 1 and 2, output stream 1 is always selected and
stream 2 can be selected or deselected by the game, by setting or clearing
bit 0 of 'Flags 2'.

7.4

In Versions 3 and later, all four output streams can be selected
or deselected using the output_stream opcode. In addition, stream 2
can be selected or deselected by setting or clearing bit 0 of 'Flags 2'.
Whichever method is used, the interpreter must ensure that this flag
holds the current status of stream 2. ('A Mind Forever Voyaging'
requires this.)

7.5

*** Because of the print_unicode opcode, it is possible for
arbitrary Unicode characters to be sent to the output streams: that is,
for characters which are not in the ZSCII set at all, even in the
"extra characters" range.

7.5.1

See S 3.8.5.4 for rules on printing Unicode to stream 1.

7.5.2

Interpreters are free to use any representation of non-ASCII
Unicode characters in stream 2. For example, they might print
"[1a05]" to signify Unicode character $1a05; or they might be
configurable to write transcript files which conform to any chosen
ISO 8859 set.

7.5.3

When printed to stream 3, Unicode characters should be
converted to ZSCII if possible. If this is not possible, a question
mark should be printed to stream 3.

7.5.4

Non-ZSCII characters never need to be printed to stream 4.

7.6

*** In Versions 5 and later, the Z-machine has the ability to load
and save files (using optional operands with the save and restore
opcodes: these operands were not used in Infocom's Version 5 games,
but I wish to specify them as in Version 5 anyway).

7.6.1

*** Filenames have the following format (approximately the MS-DOS
8.3 rule): one to eight alphanumeric characters, a full stop and zero to
three alphanumeric characters (the "file extension").

7.6.1.1

The interpreter must convert all filenames to upper case before
use. If no full stop is given, ".AUX" should be appended.

7.6.1.2

Games should avoid the extensions ".INF", ".H", ".Z"
followed by a number or ".SAV": otherwise they may be in danger of erasing
their own object code, source code or saved game files.

7.6.2

*** Saved files are not associated with any particular session
of a game. They are not part of the "state of play".

7.6.3

*** A game may depend on having up to 32 auxiliary files (with
different names).

7.6.4

File-handling errors such as "disc corrupt" and "disc full"
should be reported directly to the player by the interpreter. The error
"file not found" should only cause a failure return code from restore.

7.6.5

Interpreters are allowed to not support access to external files (such as with
output_stream 2, or the extra features of save and restore), or to only support
some methods of access. Interpreters should support these features if possible,
as some games may rely on external files, and in any case transcripts are very
useful for testing, but in some environments such access is not feasible.

7.6.5.1

An attempt by the game to use save or restore in a manner not supported by the
interpreter should simply return 0 as with any failure, and the game should
notice and take appropriate actions.

7.6.5.2

An attempt by the game to use streams to access external files which is not
supported by the interpreter should ideally print a warning to the user that
the functionality is not available, and otherwise do nothing.

Remarks

The ITF interpreter incorrectly applies buffering when printing to
the upper window.

Note that the requirement 7.1.2.1.1, that usages of stream 3 can be
'nested', is new in Standard 1.0. This is potentially important for
Inform games, as stream 3 is often used to examine text before printing,
for instance to choose between the articles "a" and "an" in front
of an object name. But the process of printing an object name may
itself require a usage of stream 3, and so on.

An ambiguous point about output stream 4 is whether it should contain
the answers to interpreter questions like "what file name should your
saved game have?": it can actually be quite useful to be able to include
such answers in test script files. (When running a long script, I often
save the game at several places during it, in order to save time in
re-running passages.)

An interpreter should be able to write time delays (for timed input),
accented characters or mouse clicks into stream 4 (i.e., to a script file).
One possible style to record this information might be:

take lamp an ordinary command
turn it on.[154] command, full stop, then keypad 9
(which might abbreviate for NE)
look unde[0] timed out input
look under the rock the same input continuing
[254][10][6] mouse-click at (10,6)

A typical auxiliary file might be one containing the player's preferred
choices. This would be created when he first changed any of the default
settings, and loaded (if present) whenever the game started up.