Text may be printed in any font of the interpreter's choice, variable- or fixed-pitch: except that when bit 1 of 'Flags 2' in the header is set, or when the text style has been set to Fixed Pitch, then a fixed-pitch font must be used.
8.1.1
In Version 5, the height and width of the current font (in units (see below)) should be written to bytes $27 and $26 of the header, respectively. In Version 6, these bytes are the other way round (height in $27, width in $26). The width of a font is defined as the width of its '0' character.
8.1.2
An interpreter should ideally provide 4 fonts, with ID numbers as follows:
1: the normal font 2: a picture font 3: a character graphics font 4: a Courier-style font with fixed pitch(In addition, font ID 0 means "the previous font".) Ideally all text styles should be available for each font (for instance, Courier bold should be obtainable) except that font 3 need only be available in Roman and Reverse Video. Each font should provide characters for character codes 32 to 126 (plus character codes for any accented characters with codes greater than 127 which are being implemented as single accented letters on-screen).
8.1.3
*** A game must not use fonts other than 1 unless allowed to by the interpreter: see the set_font opcode for how to give or refuse permission. (This paragraph is marked *** because existing Infocom games determined the availability of font 3 for 'Beyond Zork' in a complicated and unsatisfactory way: see S 16.)
8.1.3.1
*** It is legal for a game to change font at any time, including halfway through the printing of a word. (This might be needed to introduce exotic foreign accents in the future.)
8.1.4
The specification of the "picture font" is unknown (conjecturally, it was intended to provide pictures before Version 6 was properly developed). Interpreters need not implement it.
8.1.5
The specification of the character graphics font is given in S 16.
8.1.5.1
In Version 5 (only), an interpreter which cannot provide the character graphics font should clear bit 3 of 'Flags 2' in the header.
If there is room, the right hand side of the status line should display:
The following codes are used to refer to colours:
-1 = the colour of the pixel under the cursor (if any) 0 = the current setting of this colour 1 = the default setting of this colour 2 = black 3 = red 4 = green 5 = yellow 6 = blue 7 = magenta 8 = cyan 9 = white 10 = darkish grey (MSDOS interpreter number) 10 = light grey (Amiga interpreter number) 11 = medium grey (ditto) 12 = dark grey (ditto)Colours 10, 11, 12 and -1 are available only in Version 6. In Version 6 the pictures in some graphics files use colours beyond the above: if so the result of "the colour under the cursor" is permitted to be stored with value 16 or greater.
8.3.2
If the interpreter cannot produce colours, it should clear bit 0 of 'Flags 1' in the header. In Version 6 it should write colours 2 and 9 (black and white), either way round, into the default background and foreground colours in bytes $2c and $2d of the header.
8.3.3
If the interpreter can produce colours, it should set bit 0 of 'Flags 1' in the header, and write its default background and foreground colours into bytes $2c and $2d of the header.
8.3.4
If a game wishes to use colours, it should have bit 6 in 'Flags 2' set in its story file. (However, an interpreter should not rule out the use of colours just because this has not been done.)
The screen model for Versions 1 and 2 is as follows:
The screen can only be printed to (like a teletype) and there is no control of the cursor.
The screen model for Version 3 is as follows:
Printing onto the upper window overlays whatever text is already there.
When a screen split takes place in Version 3, the upper window is cleared.
The screen model for Versions 4 and later, except Version 6, is as follows:
It is legal to change text style at any point, including in the middle of a word being printed.
An interpreter should use a fixed-pitch font when printing on the upper window.
Clearing regions of the screen:
The screen model for Version 6 is as follows:
There are four attributes, numbered as follows:
0: wrapping 1: scrolling 2: text copied to output stream 2 (the transcript, if selected) 3: buffered printingEach can be turned on or off, using the window_style opcode.
8.8.3.1.1
"Wrapping" is the continuation of printed text from one line to the next. Text running up to the right margin will continue from the left margin of the following line. If "wrapping" is off then characters will be printed until no more can be fitted in without hitting the right margin, at which point the cursor will move to the right margin and stay there, so that any further text will be ignored.
8.8.3.1.2
"Buffered printing" means that text to be printed in the window is temporarily stored in a buffer and only flushed onto the screen at intervals convenient for the interpreter.
8.8.3.1.2.1
"Buffered printing" has two practical effects: firstly it causes a delay before printed text actually appears.
8.8.3.1.2.2
Secondly it affects the way "wrapping" is done. If "buffered printing" is on, then text is wrapped after the last word which could fit on a line. If not, then text is wrapped after the last character that could fit.
Example: suppose the text "Here is an abacus" is printed in a narrow window. The appearance (after the buffer has been flushed, if there is buffered printing) might be:
|...margins....| wrapping on buffering on Here is an abacus^ off buffering on Here is an aba^ wrapping on buffering off Here is an aba cus^ off buffering off Here is an aba^where the caret denotes the final position of the cursor. (Games often alter "wrapping": it would normally be on for a window holding running text but off for a status-line window, which is why window 0 has "wrapping" on by default but all other windows have "wrapping" off by default. On the other hand all windows have "buffered printing" on by default and games only alter this in rare circumstances to avoid delays in the appearance of individual printed characters.)
8.8.3.2
There are 16 properties, numbered as follows:
0 y coordinate 6 left margin size 12 font number 1 x coordinate 7 right margin size 13 font size 2 y size 8 newline interrupt routine 14 attributes 3 x size 9 interrupt countdown 15 line count 4 y cursor 10 text style 5 x cursor 11 colour dataEach property is a standard Z-machine number and is readable with get_wind_prop and writeable with put_wind_prop. However, a game should only use put_wind_prop to set the newline interrupt routine, the interrupt countdown and the line count: everything else is either set by the interpreter or by specialised opcodes (such as set_font).
8.8.3.2.1
If a window has character wrapping, then text is clipped to stay inside the left and right margins. After a new-line, the cursor moves to the left margin on the next line. Margins can be set with set_margins but this should only be done just after a newline or just after the window has been selected. (These values are margin sizes in pixels, and are by default 0.)
8.8.3.2.2
If the interrupt countdown is set to a non-zero value (which by default it is not), then the line count is decremented on each new-line, and when it hits zero the routine whose packed address is stored in the "newline interrupt routine" property is called before text printing resumes. (This routine may, for example, meddle with margins to roll text around a crinkly-shaped picture.) The interrupt routine should not attempt to print anything.
8.8.3.2.2.1
Because of an Infocom bug, if the interpreter number is 6 (for MSDOS) and the story file is 'Zork Zero' release 393.890714, but in no other case, the interpreter must do the following instead: (1) move to the new line, (2) put the cursor at the current left margin, (3) call the interrupt routine (if it's time to do so). This is the least bad way to get around a basic inconsistency in existing Infocom story files and interpreters.
8.8.3.2.2.2
Note that the set_margins opcode, which is often used by newline interrupt routines (to adjust the shape of a margin as it flows past a picture), automatically moves the cursor if the change in margins would leave the cursor outside them. The effect will depend, unfortunately, on which sequence of events above takes place.
8.8.3.2.2.3
A line count is never decremented below -999.
8.8.3.2.3
The text style is set just as in Version 4, using set_text_style (which sets that for the current window). The property holds the operand of that instruction (e.g. 4 for italic).
8.8.3.2.4
The foreground colour is stored in the lower byte of the colour data property, the background colour in the upper byte.
8.8.3.2.5
The font height (in pixels) is stored in the upper byte of the font size property, the font width (in pixels) in the lower byte.
8.8.3.2.6
The interpreter should use the line count to see when it should print "[MORE]". A line count of -999 means "never print [MORE]". (Version 6 games often set line counts to manipulate when "[MORE]" is printed.)
8.8.3.2.7
If an attempt is made by the game to read the cursor position at a time when text is held unprinted in a buffer, then this text should be flushed first, to ensure that the cursor position is accurate before being read.
8.8.3.3
All eight windows begin at (1,1). Window 0 occupies the whole screen and is initially selected. Window 1 is as wide as the screen but has zero height. Windows 2 to 7 have zero width and height. Window 0 initially has attribute 1 off and 2, 3 and 4 on (scrolling, copy to printer transcript, buffering). Windows 1 to 7 initially have attribute 4 (buffering) on, and the other attributes off.
8.8.3.4
A window can be moved with move_window and resized with window_size. If the window size is reduced so that its cursor lies outside it, the cursor should be reset to the left margin on the top line.
8.8.3.5
Each window remembers its own cursor position (relative to its own coordinates, so that the position (1,1) is at its top left). These can be changed using set_cursor (and it is legal to move the cursor for an unselected window). It is illegal to move the cursor outside the current window.
8.8.3.6
Each window can be scrolled vertically (up or down) any number of pixels, using the scroll_window opcode.
8.8.4
To some extent windows 0 and 1 mimic the behaviour of the lower and upper windows in the Version 4 screen model:
8.8.4.1
The split_screen opcode tiles windows 0 and 1 together to fill the screen, so that window 1 has the given height and is placed at the top left, while window 0 is placed just below it (with its height suitably shortened, possibly making it disappear altogether if window 1 occupies the whole screen).
8.8.4.2
An "unsplit" (that is, a split_screen 0) takes place when the entire screen is cleared with erase_window -1, if a "split" has previously occurred (meaning that windows 0 and 1 have been set up as above).
8.8.5
Screen clearing operations:
8.8.5.1
Erasing a picture is like drawing it (see below), except that the space where it would appear is painted over with background colour instead.
8.8.5.2
The current line can be erased using erase_line, either all the way to the right margin or by any positive number of pixels in that direction. The space is painted over with background colour (even if the current text style is Reverse Video).
8.8.5.3
Each window can be erased using erase_window, erasing to background colour (even if the current text style is Reverse Video).
8.8.5.3.1
Erasing window number -1 erases the entire screen to the background colour of window 0, unsplits windows 0 and 1 (see S 8.7.3.3 above) and selects window 0.
8.8.5.3.2
Erasing window -2 erases the entire screen to the current background colour. (It doesn't perform erase_window for all the individual windows, and it doesn't change any window attributes or cursor positions.)
8.8.6
Pictures may accompany the game. They are not stored in the
story file (or the Z-machine) itself, and the interpreter is simply
expected to know where to find them.
8.8.6.1
Pictures are numbered from 1 upwards (not necessarily contiguously). They can be "drawn" or "erased" (using draw_picture and erase_picture). Before attempting to do so, a game may ask the interpreter about the picture (using picture_data): this allows the interpreter to signal that the picture in question is unavailable, or to specify its height and width.
8.8.6.2
The game may, if it wishes, use the picture_table opcode to give the interpreter advance warning that a group of pictures will soon be needed (for instance, a collection of icons making up a control panel). The interpreter may want to load these pictures off disc and into a memory cache.
Some interpreters print the status line when they begin running a Version 3 game, but this is incorrect. (It means that a small game printing text and then quitting cannot be run unless it includes an object.) The author's preferred status line formats are:
Hall of Mists 80/733 Lincoln Memorial 12:03 PMThus the score/turns block always fits in 3+1+4=8 characters and the time in 2+1+2+1+2=8 characters. (Games needing more exotic time lines, for example, should not be written in Version 3.)
The only existing Version 3 game to use an upper window is 'Seastalker' (for its sonarscope display).
Some ports of ITF apply buffering (i.e. word-wrapping) and scrolling to the upper window, with unfortunate consequences. This is why the standard Inform status line is one character short of the width of the screen.
The original Infocom files seldom use erase_window, except with window -1 (for instance 'Trinity' only uses it in this form). ITF does not implement it in any other case.
The Version 5 re-releases of older games make use of consecutive set_text_style instructions to attempt to combine boldface reverse video (in the hints system).
None of Infocom's Version 4 or 5 files use erase_line at all, and ITF implements it badly (with unpredictable behaviour in Reverse Video text style). (It's interesting to note that the Version 5 edition of 'Zork I' - one of the earliest Version 5 files -- blanks out lines by looking up the screen width and printing that many spaces.)
It's recommended that a Version 5 interpreter always use units to correspond to characters: that is, characters occupy $1\times 1$ units. 'Beyond Zork' was written in the expectation that it could be using either 1x1 or 8x8, and contains correct code to calculate screen positions whatever units are used. (Infocom's Version 5 interpreter for MSDOS could either run in a text mode, 1x1, or a graphics mode, 8x8.) However, the German translation of 'Zork I' contains incorrect code to calculate screen positions unless 1x1 units are used.
Note that a minor bug in Zip writes bytes $22 to $25 in the header as four values, giving the screen dimensions in the form left, right, top, bottom: provided units are characters (i.e. provided the font width and height are both 1) then since "left" and "top" are both 0, this bug has no effect.
Some details of the known IBM graphics files are given in Paul David Doherty's "Infocom Fact Sheet". See also Mark Howell's program "pix2gif", which extracts pictures to GIF files. (This is one of his "Ztools" programs.)
Although Version 6 graphics files are not specified here, and were released in several different formats by Infocom for different computers, a consensus seems to have emerged that the MCGA pictures are the ones to adopt (files with filenames *.MG1). These are visually identical to Amiga pictures (whose format has been deciphered by Mark Knibbs). However, some Version 6 story files were tailored to the interpreters they would run on, and use the pictures differently according to what they expect the pictures to be. (For instance, an Amiga-intended story file will use one big Amiga-format picture where an MSDOS-intended story file will use several smaller MCGA ones.)
The easiest option is to interpret only DOS-intended Version 6 story files and only MCGA pictures. But it may be helpful to examine the Frotz source code, as Frotz implements draw_picture and picture_data so that Amiga and Macintosh forms of Version 6 story files can also be used.
It is generally felt that newly-written graphical games should not imitate the old Infocom graphics formats, which are very awkward to construct and have been overtaken by technology. Instead, the draft Blorb proposal for packaging up resources with Z-machine games calls for PNG format graphics glued together in a fairly simple way. An ideal Version 6 interpreter ought to understand both the four Infocom picture-sets and any Blorb set, thus catering for old and new games alike.
The line count of -999 preventing "[MORE]" is a device used by the demonstration mode of 'Zork Zero'.
|...margins....| word wrap Here is an abacus^ char wrap Here is an aba cus^ char clip Here is an aba^then Infocom's interpreters behave as follows:
Apple II MSDOS Macintosh Amiga A0 off, A3 off char clip(LR) char clip() --- --- A0 off, A3 on char clip(LR) char clip(LR) --- --- A0 on, A3 off word wrap char wrap --- --- A0 on, A3 on word wrap word wrap --- --- buffer_mode off --- --- char wrap char clip(L) buffer_mode on --- --- word wrap word wrapHere "---" means that the interpreter ignores the given state, and the presence of L, R or both after "char clipp" indicates which of the left and right margins are respected. The Amiga behaviour may be due to a bug and two bugs have also been found in the MSDOS implementation. Under this standard, the appearance is as follows:
Standard A0 off, A3 off char clip(LR) A0 off, A3 on char clip(LR) A0 on, A3 off char wrap A0 on, A3 on word wrap buffer_mode off --- buffer_mode on ---Due to a bug or an oversight, the V6 story files for all interpreters use buffer_mode once: to remove buffering while printing "Please wait..." with a row of full stops trickling out during a slow operation. Buffering would frustrate this, but fortunately on modern computers the operation is no longer slow and so the bug does not cause trouble.
Section 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 / 10 / 11 / 12 / 13 / 14 / 15 / 16
Appendix A / B / C / D / E / F