-
Notifications
You must be signed in to change notification settings - Fork 4
/
sect08.html
1058 lines (893 loc) · 42.1 KB
/
sect08.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
11/06/2014<!DOCTYPE html>
<html>
<head>
<title>The Z-Machine Standards Document</title>
<link rel="stylesheet" type="text/css" href="zspec.css">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
</head>
<body>
<img class="icon" src="images/icon08.gif" alt="">
<h1>8. The screen model</h1>
<hr>
<p>8.1 <a href="#8.1">Fonts</a> /
8.2 <a href="#8.2">Status line</a> /
8.3 <a href="#8.3">Text colours</a> /
8.4 <a href="#8.4">Screen dimensions</a> /
8.5 <a href="#8.5">Screen model (V1, V2)</a> /
8.6 <a href="#8.6">Screen model (V3)</a> /
8.7 <a href="#8.7">Screen model (V4, V5)</a> /
8.8 <a href="#8.8">Screen model (V6)</a>
</p>
<hr>
<h2 id="8.1">8.1</h2>
<p>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, font 4 has been selected, or when the text style has been set to Fixed Pitch,
then a fixed-pitch font must be used. The fixed pitch-bit is deprecated in Version 5 and later,
and interpreter support in Version 6 is optional.
</p>
<h2 id="8.1.1">8.1.1</h2>
<p>In Version 5, the height and width of the current
font (in units (see below)) should be written to bytes <strong>$27</strong> and
<strong>$26</strong> of the header, respectively. In Version 6, these bytes
are the other way round (height in <strong>$27</strong>, width in <strong>$26</strong>).
The width of a font is defined as the width of its
'0' character.
</p>
<p>This must be updated whenever the size of the current font changes, for instance if a new
window is selected, the current font is changed, or a different style is chosen.
</p>
<h2 id="8.1.2">8.1.2</h2>
<p>An interpreter should ideally provide 4 fonts, with ID numbers
as follows:
</p>
<pre>
1: the normal font
2: a picture font
3: a character graphics font
4: a Courier-style font with fixed pitch
</pre>
<p>(Selecting font ID 0 is legal, and does not change the current 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).
</p>
<h2 id="8.1.3">8.1.3</h2>
<p><strong>***</strong>
A game must not use fonts other than 1 unless allowed
to by the interpreter: see the <strong>set_font</strong> opcode for how to give
or refuse permission. (This paragraph is marked <strong>***</strong> because
existing Infocom games determined the availability of font 3 for
'Beyond Zork' in a complicated and unsatisfactory way: see <strong>§</strong> 16.)
</p>
<h2 id="8.1.3.1">8.1.3.1</h2>
<p><strong>***</strong>
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.)
</p>
<h2 id="8.1.4">8.1.4</h2>
<p>The specification of the "picture font" is unknown
(conjecturally, it was intended to provide pictures before Version
6 was properly developed).
Interpreters should not implement it, and should refuse
permission to any game requesting it.
</p>
<h2 id="8.1.5">8.1.5</h2>
<p>The specification of the character graphics font is given
in <strong>§</strong> 16.
</p>
<h2 id="8.1.5.1">8.1.5.1</h2>
<p>In Version 5 (only), an interpreter which cannot provide
the character graphics font should clear bit 3 of 'Flags 2' in the
header.
</p>
<h2 id="8.1.6">8.1.6</h2>
<p>Any new fonts will have numbers higher than 4. Fonts 5-1023 are reserved
for future Standards to specify. Local use may be made of higher font numbers.
</p>
<h2 id="8.2">8.2</h2>
<p>In Versions 1 to 3, a status line should be printed by the
interpreter, as follows. In Version 3, it must set bit 4 of
'Flags 1' in the header if it is unable to produce a status line.
</p>
<h2 id="8.2.1">8.2.1</h2>
<p>In Versions 1 and 2, all games are "score games". In
Version 3, if bit 1 of 'Flags 1' is clear then the game is a "score game";
if it is set, then the game is a "time game".
</p>
<h2 id="8.2.2">8.2.2</h2>
<p>The short name of the object whose number is in the first global
variable should be printed on the left hand side of the line.
</p>
<h2 id="8.2.2.1">8.2.2.1</h2>
<p>Whenever the status line is being printed the first global
must contain a valid object number. (It would be useful if interpreters
could protect themselves in case the game accidentally violates this
requirement.)
</p>
<h2 id="8.2.2.2">8.2.2.2</h2>
<p>If the object's short name exceeds the available room on
the status line, the author suggests that an interpreter should break
it at the last space and append an ellipsis "...". There is no
guaranteed maximum length for location names but an interpreter should
expect names of length up to at least 49 characters.
</p>
<h2 id="8.2.3">8.2.3</h2>
<p>If there is room, the right hand side of the status line should
display:
</p>
<h2 id="8.2.3.1">8.2.3.1</h2>
<p>For "score games": the score and number of turns, held in
the values of the second and third global variables respectively. The
score may be assumed to be in the range -99 to 999 inclusive, and
the turn number in the range 0 to 9999.
</p>
<h2 id="8.2.3.2">8.2.3.2</h2>
<p>For "time games": the time, in the form <strong>hours:minutes</strong> (held
in the second and third globals). The time may be given on a 24-hour clock
or the number of hours may be reduced modulo 12 (but if so, "AM" or "PM"
should be appended). Either way the player should be able to see the
difference between 4am and 4pm, for example. The hours global may be
assumed to be in the range 0 to 23 and the minutes global in the range
0 to 59.
</p>
<h2 id="8.2.4">8.2.4</h2>
<p>The status line is updated in exactly two circumstances: when
a <strong>show_status</strong> opcode is executed, and just before the keyboard is
read by <strong>read</strong>. (It is not displayed when the game begins.)
</p>
<h2 id="8.3">8.3</h2>
<p>Under Versions 5 and later, text printing has a current
foreground and background colour. In Version 6, each window has its
own pair. (Note that a Version 6 interpreter going under the
Amiga interpreter number must use the same pair of colours for
all windows when running Infocom's games. If either is changed,
then the interpreter must change the colour of all text on the screen to match.
This simulates the Amiga hardware, which used two logical colours
for text and switched palette to change their physical colour.
This behaviour should not occur when running non-Infocom games,
and modern games should never expect it. An interpreter that does
not wish to handle this behaviour at all should avoid using the
Amiga interpreter number when running Infocom's Version 6 games.)
</p>
<h2 id="8.3.1">8.3.1</h2>
<p>The following codes are used to refer to colours:</p>
<pre>
-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)
</pre>
<p>Colours 10, 11, 12 and -1 are available only in Version 6.</p>
<h2 id="8.3.2">8.3.2</h2>
<p>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 <strong>$2c</strong> and <strong>$2d</strong> of the
header.
</p>
<h2 id="8.3.3">8.3.3</h2>
<p>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 <strong>$2c</strong> and <strong>$2d</strong> of the header.
</p>
<h2 id="8.3.4">8.3.4</h2>
<p>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.)
</p>
<h2 id="8.3.5">8.3.5</h2>
<p>In version 6, if an "under the cursor" colour has been requested by the
game, then the foreground or background colour shown in window property 11 is
implementation defined, with two exceptions:
</p>
<h2 id="8.3.5.1">8.3.5.1</h2>
<p>If the colour selected was one of the standard set (2-15), then
that colour is indicated in property 11.
</p>
<h2 id="8.3.5.2">8.3.5.2</h2>
<p>If the colour selected was not one of the standard set (this can happen
when using graphics, which may use many more colours), the colour
shown in property 11 will be >= 16.
</p>
<h2 id="8.4">8.4</h2>
<p>The screen should ideally be at least 60 characters wide by 14 lines
deep. (Old Apple II interpreters had a 40 character width and some more
recent laptop ones have a 9 line height, but implementors should seek to
avoid these extremes if possible.) The interpreter may change the exact
dimensions whenever it likes but must write the current height (in lines)
and width (in characters) into bytes <strong>$20</strong> and <strong>$21</strong>
in the header.
</p>
<h2 id="8.4.1">8.4.1</h2>
<p>The interpreter should use the screen height for calculating when to pause
and print "[MORE]".
</p>
<p>In theory, a screen height of 255 lines means "infinite
height" (in case, say, the screen is actually a teletype printer), in which
case the interpreter should never stop printing for a "[MORE]" prompt. In
practice, however, interpreters should avoid setting the height to 255 as it
causes serious problems with some Inform and Infocom games. Instead, the
interpreter should simply pick a number for the screen height based on a
sensible maximum size for screen operations such as <strong>split_window</strong>.
</p>
<h2 id="8.4.2">8.4.2</h2>
<p>Screen dimensions are measured in notional "units". In
Versions 1 to 4, one unit is simply the height or width of one character.
In Version 5 and later, the interpreter is free to implement units as
anything from character sizes down to individual pixels.
</p>
<h2 id="8.4.3">8.4.3</h2>
<p>In Version 5 and later, the screen's width and height in units
should be written to the words at <strong>$22</strong> and <strong>$24</strong>.
</p>
<h2 id="8.5">8.5</h2>
<p>The screen model for Versions 1 and 2 is as follows:
</p>
<h2 id="8.5.1">8.5.1</h2>
<p>The screen can only be printed to (like a teletype) and there
is no control of the cursor.
</p>
<h2 id="8.5.2">8.5.2</h2>
<p>At the start of a game, the screen should be cleared and the text
cursor placed at the bottom left (so that text scrolls upwards as the game
gets under way).
</p>
<h2 id="8.6">8.6</h2>
<p>The screen model for Version 3 is as follows:</p>
<h2 id="8.6.1">8.6.1</h2>
<p>The screen is divided into a lower and an upper window and at any
given time one of these is selected. (Initially it is the lower
window.) The game uses the <strong>set_window</strong> opcode to select one of the
two. Each window has its own cursor position at which text is
printed. Operations in the upper window do not move the cursor of the
lower. Whenever the upper window is selected, its cursor position is
reset to the top left. Selecting, or re-sizing, the upper window does
not change the screen's appearance.
</p>
<h2 id="8.6.1.1">8.6.1.1</h2>
<p>The upper window has variable height (of n lines)
and the same width as the screen. This should be displayed on the n lines
of the screen below the top one (which continues to hold the status line).
Initially the upper window has
height 0. When the lower window is selected, the game can split off
an upper window of any chosen size by using the <strong>split_window</strong> opcode.
</p>
<h2 id="8.6.1.1.1">8.6.1.1.1</h2>
<p>Printing onto the upper window overlays whatever text is
already there.
</p>
<h2 id="8.6.1.1.2">8.6.1.1.2</h2>
<p>When a screen split takes place in Version 3, the upper
window is cleared.
</p>
<h2 id="8.6.1.2">8.6.1.2</h2>
<p>An interpreter need not provide the upper window at all. If
it is going to do so, it should set bit 5 of 'Flags 1' in the header to
signal this to the game. It is only legal for a game to use
<strong>set_window</strong> or <strong>split_window</strong> if this bit has been set.
</p>
<h2 id="8.6.1.3">8.6.1.3</h2>
<p>Following a "restore" of the game, the interpreter should
automatically collapse the upper window to size 0.
</p>
<h2 id="8.6.2">8.6.2</h2>
<p>When text reaches the bottom right of the lower window, it
should be scrolled upwards. The upper window should never be scrolled:
it is legal for a character to be printed on the bottom right position
of the upper window (but the position of the cursor after this operation
is undefined: the author suggests that it stay put).
</p>
<h2 id="8.6.3">8.6.3</h2>
<p>At the start of a game, the screen should be cleared and the text
cursor placed at the bottom left (so that text scrolls upwards as the game
gets under way).
</p>
<h2 id="8.7">8.7</h2>
<p>The screen model for Versions 4 and later, except Version 6,
is as follows:
</p>
<h2 id="8.7.1">8.7.1</h2>
<p>Text can be printed in five different styles (modelled on the
VT100 design of terminal). These are: Roman (the default), Bold, Italic,
Reverse Video (usually printed with foreground and background colours
reversed) and Fixed Pitch. The specification does not require the
interpreter to be able to display more than one of these at once (e.g. to
combine italic and bold), and most interpreters can't. If the interpreter
is going to allow certain combinations, then note that changing back to
Roman should turn off all the text styles currently active.
</p>
<h2 id="8.7.1.1">8.7.1.1</h2>
<p>An interpreter need not provide Bold or Italic (even for font 1)
and is free to interpret them broadly. (For example, rendering bold-face by
changing the colour, or rendering italic with underlining.)
</p>
<h2 id="8.7.1.2">8.7.1.2</h2>
<p>It is legal to change text style at any point, including in
the middle of a word being printed.
</p>
<h2 id="8.7.2">8.7.2</h2>
<p>There are two "windows", called "upper" and "lower": at
any given time one of these two is selected. (Initially it is the lower
window.) The game uses the <strong>set_window</strong> opcode to select
one of the two. Each window has its own cursor position at which text is
printed. Operations in the upper window do not move the cursor of the
lower. Whenever the upper window is selected, its cursor position is
reset to the top left.
</p>
<h2 id="8.7.2.1">8.7.2.1</h2>
<p>The upper window has variable height (of n lines) and the
same width as the screen. (It is usual for interpreters to print the
upper window on the top n lines of the screen, overlaying any text
which is already there, having been printed in the lower window some
time ago.) Initially the upper window has height 0. When the lower
window is selected, the game can split off an upper window of any
chosen size by using the <strong>split_window</strong> opcode.
</p>
<h2 id="8.7.2.1.1">8.7.2.1.1</h2>
<p>It is unclear exactly what <strong>split_window</strong> should do if
the upper window is currently selected. The author suggests that
it should work as usual, leaving the cursor where it is if the
cursor is still inside the new upper window, and otherwise moving
the cursor back to the top left. (This is analogous to the Version 6
practice.)
</p>
<h2 id="8.7.2.2">8.7.2.2</h2>
<p>In Version 4, the lower window's cursor is always on
the bottom screen line. In Version 5 it can be at any line which is
not underneath the upper window. If a split takes place which would
cause the upper window to swallow the lower window's cursor position,
the interpreter should move the lower window's cursor down to the
line just below the upper window's new size.
</p>
<h2 id="8.7.2.3">8.7.2.3</h2>
<p>The position of the cursor in the upper window can be set and retrieved
with <strong>set_cursor</strong> and <strong>get_cursor</strong>.
</p>
<h2 id="8.7.2.3.1">8.7.2.3.1</h2>
<p>When the upper window is selected, its cursor position can be moved with
<strong>set_cursor</strong>. This position is given in units in the
form (row, column), with (1,1) at the top left. The opcode has no effect
when the lower window is selected. It is illegal to move the cursor outside
the current size of the upper window.
</p>
<h2 id="8.7.2.3.2">8.7.2.3.2</h2>
<p>When either the upper or lower windows are selected, <strong>get_cursor</strong>
returns the position of the cursor (in units) in the upper window.
</p>
<h2 id="8.7.2.4">8.7.2.4</h2>
<p>An interpreter should use a fixed-pitch font when printing on
the upper window.
</p>
<h2 id="8.7.2.5">8.7.2.5</h2>
<p>In Versions 3 to 5, text buffering is never active in the
upper window (even if a game begins printing there without having
turned it off).
</p>
<h2 id="8.7.3">8.7.3</h2>
<p>Clearing regions of the screen:</p>
<h2 id="8.7.3.1">8.7.3.1</h2>
<p>When text reaches the bottom right of the lower window, it
should be scrolled upwards. (When the text style is Reverse Video
the new blank line should <strong>not</strong> have reversed colours.) The upper
window should never be scrolled: it is legal for a character to be
printed on the bottom right position of the upper window (but the
position of the cursor after this operation is undefined: the author
suggests that it stay put).
</p>
<h2 id="8.7.3.2">8.7.3.2</h2>
<p>Using the opcode <strong>erase_window</strong>, the specified window
can be cleared to background colour. (Even if the text style is Reverse
Video the new blank space should not have reversed colours.)
</p>
<h2 id="8.7.3.2.1">8.7.3.2.1</h2>
<p>In Versions 5 and later, the cursor for the window being erased
should be moved to the top left. In Version 4, the lower window's cursor
moves to its bottom left, while the upper window's cursor moves to top left.
</p>
<h2 id="8.7.3.3">8.7.3.3</h2>
<p>Erasing window -1 clears the whole screen to the
background colour of the lower screen, collapses the upper window
to height 0, moves the cursor of the lower screen to bottom
left (in Version 4) or top left (in Versions 5 and
later) and selects the lower screen. The same operation should
happen at the start of a game.
</p>
<h2 id="8.7.3.4">8.7.3.4</h2>
<p>Using <strong>erase_line</strong> in the upper window should erase
the current line from the cursor position to the right-hand edge,
clearing it to background colour. (Even if the text style is
Reverse Video the new blank space should not have reversed colours.)
</p>
<h2 id="8.8">8.8</h2>
<p> The screen model for Version 6 is as follows:</p>
<h2 id="8.8.1">8.8.1</h2>
<p>The display is an array of pixels. Coordinates are usually
given (in units) in the form (y,x), with (1,1) in the top left.
</p>
<h2 id="8.8.2">8.8.2</h2>
<p>If the interpreter thinks the screen should be redrawn
(e.g. because a menu window has been clicked over it), it may set bit
2 of 'Flags 2'. The game is expected to notice, take action and clear
the bit. (However, a more efficient interpreter would handle redraws itself.)
</p>
<h2 id="8.8.3">8.8.3</h2>
<p>There are eight "windows", numbered 0 to 7. The code -3
is used as a window number to mean "the currently selected window".
This selection can be changed with the <strong>set_window</strong> opcode.
Windows are invisible and usually lie on top of each other. All text
and graphics plotting is always clipped to the current window,
and anything showing through is plotted onto the screen.
Subsequent movements of the window do not move what was printed and
there is no sense in which characters or graphics 'belong' to any
particular window once printed. Each window has a position (in units),
a size (in units), a cursor position within it (in units, relative to its
own origin), a number of flags called "attributes" and a number
of variables called "properties".
</p>
<h2 id="8.8.3.1">8.8.3.1</h2>
<p>There are four attributes, numbered as follows:</p>
<pre>
0: wrapping
1: scrolling
2: text copied to output stream 2 (the transcript, if selected)
3: buffered printing
</pre>
<p>Each can be turned on or off, using the <strong>window_style</strong> opcode.</p>
<h2 id="8.8.3.1.1">8.8.3.1.1</h2>
<p>"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.
</p>
<h2 id="8.8.3.1.2">8.8.3.1.2</h2>
<p>"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.
</p>
<h2 id="8.8.3.1.2.1">8.8.3.1.2.1</h2>
<p>"Buffered printing" has two practical effects:
firstly it causes a delay before printed text actually appears.
</p>
<h2 id="8.8.3.1.2.2">8.8.3.1.2.2</h2>
<p>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.
</p>
<p>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:
</p>
<pre>
|...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^
</pre>
<p>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.)
</p>
<h2 id="8.8.3.2">8.8.3.2</h2>
<p>There are 16 properties, numbered as follows:</p>
<pre>
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 data
</pre>
<p>Each property is a standard Z-machine number and is readable
with <strong>get_wind_prop</strong> and writeable with <strong>put_wind_prop</strong>. However,
a game should only use <strong>put_wind_prop</strong> 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 <strong>set_font</strong>).
</p>
<h2 id="8.8.3.2.1">8.8.3.2.1</h2>
<p>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 <strong>set_margins</strong> 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.)
</p>
<h2 id="8.8.3.2.2">8.8.3.2.2</h2>
<p>If the interrupt countdown is set to a non-zero value (which by default it
is not), then it 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.
</p>
<h2 id="8.8.3.2.2.1">8.8.3.2.2.1</h2>
<p>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.
</p>
<h2 id="8.8.3.2.2.2">8.8.3.2.2.2</h2>
<p>Note that the <strong>set_margins</strong> 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.
</p>
<h2 id="8.8.3.2.3">8.8.3.2.3</h2>
<p>The text style is set just as in Version 4, using
<strong>set_text_style</strong> (which sets that for the current window). The
property holds the operand of that instruction (e.g. 4 for italic).
</p>
<h2 id="8.8.3.2.4">8.8.3.2.4</h2>
<p>The foreground colour is stored in the lower byte of the
colour data property, the background colour in the upper byte.
</p>
<h2 id="8.8.3.2.5">8.8.3.2.5</h2>
<p>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.
</p>
<p>This must be updated whenever the font size changes, for instance
because of <strong>set_font</strong> or <strong>set_text_style</strong>.
</p>
<h2 id="8.8.3.2.6">8.8.3.2.6</h2>
<p>The line count is incremented on each new-line, unless it is
set to -999. 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.) The line count should never be set to less
than -999.
</p>
<h2 id="8.8.3.2.7">8.8.3.2.7</h2>
<p>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.
</p>
<h2 id="8.8.3.3">8.8.3.3</h2>
<p>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.
</p>
<h2 id="8.8.3.4">8.8.3.4</h2>
<p>A window can be moved with <strong>move_window</strong> and resized with
<strong>window_size</strong>. 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.
</p>
<h2 id="8.8.3.5">8.8.3.5</h2>
<p>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 <strong>set_cursor</strong> (and it is legal to move the cursor
for an unselected window). It is illegal to move the cursor outside
the current window.
</p>
<h2 id="8.8.3.6">8.8.3.6</h2>
<p>Each window can be scrolled vertically (up or down) any
number of pixels, using the <strong>scroll_window</strong> opcode.
</p>
<h2 id="8.8.4">8.8.4</h2>
<p>To some extent windows 0 and 1 mimic the behaviour of the
lower and upper windows in the Version 4 screen model:
</p>
<h2 id="8.8.4.1">8.8.4.1</h2>
<p>The <strong>split_window</strong> opcode tiles windows 0 and 1 together
to fill the screen vertically, so that window 1 has the given height and
has its y coordinate set to 1, while window 0 is placed just below it
(with its height suitably shortened, possibly making it disappear
altogether if the height of window 1 occupies the whole screen).
</p>
<p>The x coordinate and width of the windows are not changed.</p>
<h2 id="8.8.4.2">8.8.4.2</h2>
<p>An "unsplit" (that is, a <strong>split_window 0</strong>) takes place
when the entire screen is cleared with <strong>erase_window -1</strong>, if a
"split" has previously occurred (meaning that windows 0 and 1
have been set up as above).
</p>
<h2 id="8.8.5">8.8.5</h2>
<p>Screen clearing operations:</p>
<h2 id="8.8.5.1">8.8.5.1</h2>
<p>Erasing a picture is like drawing it (see below), except
that the space where it would appear is painted over with background
colour instead.
</p>
<h2 id="8.8.5.2">8.8.5.2</h2>
<p>The current line can be erased using <strong>erase_line</strong>, 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).
</p>
<h2 id="8.8.5.3">8.8.5.3</h2>
<p>Each window can be erased using <strong>erase_window</strong>, erasing to
background colour (even if the current text style is Reverse Video).
</p>
<h2 id="8.8.5.3.1">8.8.5.3.1</h2>
<p>Erasing window number -1 erases the entire screen to
the background colour of window 0, unsplits windows 0 and 1
(see <strong>§</strong> 8.7.3.3 above) and selects window 0.
</p>
<h2 id="8.8.5.3.2">8.8.5.3.2</h2>
<p>Erasing window -2 erases the entire screen to the current
background colour. (It doesn't perform <strong>erase_window</strong> for all the
individual windows, and it doesn't change any window attributes or
cursor positions.)
</p>
<h2 id="8.8.6">8.8.6</h2>
<p>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.
</p>
<h2 id="8.8.6.1">8.8.6.1</h2>
<p>Pictures are numbered from 1 upwards (not necessarily
contiguously). They can be "drawn" or "erased" (using <strong>draw_picture</strong>
and <strong>erase_picture</strong>). Before attempting to do so, a game may ask the
interpreter about the picture (using <strong>picture_data</strong>): this allows the
interpreter to signal that the picture in question is unavailable,
or to specify its height and width.
</p>
<h2 id="8.8.6.2">8.8.6.2</h2>
<p>The game may, if it wishes, use the <strong>picture_table</strong> 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.
</p>
<hr>
<h2 id="remarks">Remarks</h2>
<p>See <strong>§</strong> 16 for comment on how 'Beyond Zork' uses fonts.</p>
<p>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:
</p>
<pre>
Hall of Mists 80/733
Lincoln Memorial 12:03 PM
</pre>
<p>Thus 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.)
</p>
<p>The only existing Version 3 game to use an upper window is 'Seastalker'
(for its sonarscope display).
</p>
<p>Some ports of <strong>ITF</strong> 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.
</p>
<p>The original Infocom files seldom use <strong>erase_window</strong>, except with window
-1 (for instance 'Trinity' only uses it in this form). <strong>ITF</strong> does not
implement it in any other case.
</p>
<p>The Version 5 re-releases of older games make use of consecutive
<strong>set_text_style</strong> instructions to attempt to combine boldface reverse video
(in the hints system).
</p>
<p>None of Infocom's Version 4 or 5 files use <strong>erase_line</strong> at all, and <strong>ITF</strong>
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.)
</p>
<p>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.
</p>
<p>Note that a minor bug in <strong>Zip</strong> writes bytes <strong>$22</strong> to <strong>$25</strong> 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.
</p>
<p>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.)
</p>
<p>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 <strong>*.MG1</strong>). 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.)
</p>
<p>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
<strong>Frotz</strong> source code, as <strong>Frotz</strong> implements <strong>draw_picture</strong> and
<strong>picture_data</strong> so that Amiga and Macintosh forms of Version 6 story
files can also be used.
</p>
<p>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
<strong>Blorb</strong> proposal for packaging up resources with Z-machine games
calls for PNG format graphics glued together in a fairly simple way.
The graphics for Infocom's Version 6 games have been made available in <strong>Blorb</strong>
format, so that understanding Infocom's picture-sets is no longer very useful.
</p>
<p>The line count of -999 preventing "[MORE]" is a device used by the
demonstration mode of 'Zork Zero'.
</p>
<p>Interpreter authors are advised that all 8 windows in Version 6 must be
treated identically. The only ways in which they are distinguished are:
</p>
<ul>
<li>Different default positions + sizes</li>
<li>Different default attributes</li>
<li>@split_window manipulates windows 0 and 1 specifically</li>
<li>Window 1 is the default mouse window</li>
</ul>
<p>Differences in interpreter behaviour must only arise from differences in
window attributes and properties.
</p>
<p>In V6, it is legal to position the cursor up against the right or bottom of a
window - eg at (1,1) in a zero-sized window or at (641,401) in 640x400
window. Indeed, this is the default state of windows 1 to 7, and the cursor
may be left at the right-hand side of a window when wrapping is off.
</p>
<p>Attempting to print text (including new-lines) when the cursor is fewer than
font_height units from the bottom of the window results in undefined
behaviour - this precludes any printing in windows less than font_height
units high.
</p>
<p>It is legal for interpreters to always show the same value in property 11 if
a sampled colour is in use. As a result, story files cannot assume
that setting a value that was read from property 11 will give the same
colour, if @set_colour -1 has been used in that window.
</p>
<p>The same rules apply if an interpreter offers non-standard default colours
although in this case it would be
ill-advised to show the same colour numbers for foreground and background -
unless they can be distinguished, non-standard default colours should
probably not be offered.
</p>
<p>If the interpreter offers a limited palette, then there is no problem, as it
can be arranged for there to be fewer than 240 distinct non-standard colours.
In an interpreter with a higher colour-depth, a good implementation would be
to use colours 16-255 to represent the last 240 distinct non-standard colours
used, re-using numbers after 240 colours have been used. This will minimize
potential problems caused by non-standard colours, particularly when set as
defaults.
</p>
<p>Regardless of the limitations on colour numbers, in Version 6 each window
must remember accurately the colour pair selected, so it is preserved across
window switches.
</p>
<hr>
<p><strong>§</strong> 8.7.2.3 states that it is illegal to move the cursor outside the current
size of the upper window. <strong>§</strong> 8.8.3.5 gives the equivalent rule for Version 6.
</p>
<p>Many modern games have been lax in obeying this rule; in particular some
of the standard Inform menu libraries have violated it. Infocom's Sherlock
also miscalculated the size of the upper window to use for box quotes.
</p>
<p>It is recommended that if the cursor is moved below the split position in
V4/V5, interpreters should execute an implicit "split_window" to contain the
requested cursor position, if possible. Diagnostics should be produced, but
should be suppressable.
</p>
<hr>
<p>Some modern Z-Machine interpeters (mainly those using Andrew Plotkin's
Glk interface standard) use slightly non-Standard behaviour for the upper
window. While this largely causes no problems, Trinity, and many more recent
Inform games, print quote boxes using a technique that is not compatible with
this implementation.
</p>
<p>Andrew Plotkin has written up some <a href="http://eblong.com/zarf/glk/quote-box.html">notes</a>
on the issue, including a workaround.
</p>
<hr>
<p>Infocom's Version 6 interpreters and story files disagree on the meaning
of window attributes 0 and 3 and the opcode <strong>buffer_mode</strong>, in such
a way that the original specification is hard to deduce from the final
behaviour. If we call the three possible ways that text can appear
"word wrap", "char wrap" and "char clip":
</p>
<pre>
|...margins....|
word wrap Here is an
abacus^
char wrap Here is an aba
cus^
char clip Here is an aba^
</pre>
<p>then Infocom's interpreters behave as follows:</p>
<pre>
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 --- ---