1 Zoom - A Z-Machine
2 ----// 8888 \\----
3
4by Andrew Hunter
5
6 Zoom was originally designed as an experiment into writing fast
7 bytecode interpreters, just over 3 years ago (first checkin into
8 the CVS repository was on 19/11/2000). Last time I timed it, it
9 could run up to around 2x faster than frotz, depending on what
10 code was being executed. It's changed a lot since then, as the
11 emphasis is now on designing a good user interface for the
12 interpreter. As I changed my main machine from a Linux PC to a
13 PowerMac about a year ago, and for another reason that will be
14 revealed later in the year, the recent development focus has been
15 on producing a Cocoa interface.
16
17 Send any bug reports to andrew@logicalshift.co.uk, and anything
18 else to andrew@logicalshift.co.uk. Zoom's homepage can be
19 located at http://www.logicalshift.co.uk/unix/zoom/
20
21 You can get the latest version of the source code at any time
22 using git:
23
24 git clone http://code.logicalshift.co.uk/zoom/zoom.git
25 git submodule init
26 git submodule update
27
28Versions
29========
30
31 This is version 1.1.5 of Zoom. As the components have gained an
32 increasing tendency to change at different rates, I've given them
33 separate versions:
34
35 Zoom interpreter core: 1.1.5
36 X11 interface: 1.1.5
37 Windows interface: 0.9.99beta5
38 Carbon interface: 1.0.1
39 Cocoa interface: 2.1.5
40 ZoomPlugins: 1.1.5
41 Spotlight importer: 1.5
42 QuickLook plugin: 1.1.5
43 CocoaGlk version: 1.0.8
44 Glulxe version: 0.4.7
45
46 Note that Zoom's display system underwent a fairly major change
47 between 1.0.0 and 1.0.1 due to the addition of version 6 support. This
48 means that the Windows version of Zoom will not compile any longer.
49 The 2.0 version of the Cocoa interface refers to the version number
50 displayed in the About box for the Macintosh version of Zoom.
51
52Compiling Zoom
53==============
54
55 (See later for Cocoa)
56
57 To get a full-featured interpreter under X windows or Carbon,
58 you'll want to have at least libpng installed. For X, having an
59 X server with Xrender and Xft is a good idea. T1Lib is optional,
60 but appears to provide improved rendering quality over Xft (which
61 seems to have great difficulties with hinting).
62
63 With all the libraries installed, ./configure && make should be
64 all that's required to build Zoom for either X or Mac OS X (Carbon).
65 Please report any build problems to the bugs address listed
66 above: Zoom should work on a reasonably wide variety of systems.
67
68 You can also build the Carbon version of Zoom by opening the
69 Zoom.pbproj file in Project Builder. The Cocoa version of Zoom has
70 to be built with XCode, using the ZoomCocoa.xcode file. Building
71 with project builder may cause problems with yacc generating corrupt
72 files, producing many spurious errors (XCode does not appear to have
73 these problems). If this occurs, delete the relevant files from
74 the build/Zoom.build/DerivedSources directory.
75
76 You may want to try the --enable-new-terp option to configure:
77 this enables an experimental new interpreter design. This gives
78 gcc's optimiser a much easier time of things (improving compile
79 times considerably). This style of interpreter produces a slight
80 (almost insignificant) performance hit.
81
82 I've experienced problems with gcc 3's optimiser: specifically,
83 it reduces the speed of some instructions by a factor of up to
84 6 (0OPs, usually, for some reason - see the results of NopMark in
85 zmark). No idea why at all - this effect is most marked with the
86 new interpreter style. Note that compiling the interpreter can be
87 a great workout for your system; on my Mac OS X machine, it needs
88 nearly 1Gb of memory to compile successfully with gcc 3.3.
89 Earlier versions of gcc require much less memory; I have
90 successfully compiled under x86 linux on a machine with 32Mb
91 of memory and gcc 2.95; the PPC version of gcc seems to require
92 much more memory for optimisation than the standard version, too.
93 Regardless, at least 256Mb of memory is recommended for those
94 that wish to compile Zoom.
95
96Compiling Zoom (Cocoa)
97======================
98
99 Before compiling, you will need to have a version of the expat
100 library unpacked into the directory containing the Zoom source
101 directory. Use a symbolic link, or rename this directory 'expat'.
102 Currently, the Zoom binaries link against expat 1.95.8: later
103 versions may also work. (Zoom is statically linked against expat
104 as it was an optional install on versions of OS X prior to 10.3)
105
106 You will also need the babel utility and the Sparkle library in the
107 directory containing the Zoom source code.
108
109 Finally, you will need the dependencies in the depend directory: this
110 means CocoaGlk at the moment. The easiest way to get these is to use git:
111 in the depends directory type this:
112
113 git clone http://code.logicalshift.co.uk/zoom/cocoaglk.git CocoaGlk
114
115 If you want to use the versions that correspond to a specific release,
116 use git checkout with the version number. For example, git checkout
117 v1.1.5. Note that CocoaGlk requires you to download versions of the
118 git and glulxe interpreters to compile it.
119
120 Rather than use the configure/automake process for this, I have
121 elected to use Xcode: to compile the new version of Zoom, load the
122 ZoomCocoa.xcode project into Xcode and hit build. Note that Xcode
123 seems to have a hard time running Yacc; if the build fails with
124 many weird errors, you will have to manually delete the relevant
125 DerivedSources (hidden in build/ZoomCocoa.build/ZoomServer.build).
126 There also seems to be an occasional problem with precompiled headers
127 that will produce similar problems (errors in Carbon headers this
128 time), but simply restarting the build process will fix this - you
129 are much more likely to see problems with building the Yacc sources.
130
131Using Zoom (X-Windows)
132======================
133
134 Running Zoom is fairly simple - zoom <filename> should do the
135 trick, where <filename> is a Z-Code file (modern files created by
136 Inform tend to have a .z5 or .z8 filename, original Infocom files
137 tend to have a .dat or .zip filename - note that the .zip stands
138 for 'Z-Code Interpreter', not PKZip as you might think). Assuming
139 you haven't tinkered with zmachine.h, Zoom will support Z-Code
140 versions 3, 4, 5, 6, 7 and 8. As of version 1.0.1beta1, version
141 6 is fully supported, as is the Standard v1.1draft6. Unicode
142 support is also much improved from this release.
143
144 Zoom needs a configuration file called '.zoomrc' in your home
145 directory. This file tells Zoom about the colours and fonts it
146 should use, and also identifies game titles. It consists of many
147 entries of the form 'game "mygame" 12.345678 { options }', where
148 'mygame' is the text that appears in the title bar, and { options }
149 is the options for this game (in curly brackets). You can omit the
150 options altogether if you want the options to be the same as the
151 default. There is also exactly one default block, which has the
152 form 'default "%s (%i.%.6s)" { options }'. The default block must
153 define the interpreter number and revision, at least 4 fonts, and
154 the default set of colours:
155
156 # Standard settings - applies to all interpreters
157 # (Note, font 4 must always be fixed-pitch)
158 default "%s (%i.%.6s)"
159 {
160 interpreter 1
161 revision Z
162
163 font 1 "-*-helvetica-medium-r-*-*-14-*-*-*-*-*-*-*" roman
164 font 2 "-*-helvetica-bold-r-*-*-14-*-*-*-*-*-*-*" bold
165 font 3 "-*-helvetica-medium-o-*-*-14-*-*-*-*-*-*-*" italic
166 font 4 "-*-courier-medium-r-*-*-14-*-*-*-*-*-*-*" fixed
167 font 5 "-*-courier-bold-r-*-*-14-*-*-*-*-*-*-*" fixed-bold
168 font 6 "-*-courier-medium-o-*-*-14-*-*-*-*-*-*-*" fixed-italic
169 font 7 "-*-courier-bold-o-*-*-14-*-*-*-*-*-*-*" fixed-bold-italic
170 font 8 "-*-helvetica-bold-o-*-*-14-*-*-*-*-*-*-*" bold-italic
171 font 9 "font3" symbolic
172
173 colours (0,0,0), (255,0,0), (0,255,0), (255,255,0), (0,0,255),
174 (255,0,255), (0,255,255), (255,255,204),
175 # These are the colours provided by DOS interpreters
176 (187, 187, 187), (136, 136, 136), (68, 68, 68)
177
178 size 80, 30
179
180 gamedir "/usr/local/share/games/zcode"
181 savedir "/home/me/zcode/save"
182 }
183
184 This illustrates most of the available options. Unless you have a
185 particular reason for setting the interpreter number and revision,
186 the values given should do a reasonable job (version 6 games, and
187 Beyond Zork benefit from setting the interpreter number).
188
189 Fonts are defined using statements of the form:
190
191 font <num> "<name>" <style>
192
193 Where <num> specifies the font number (note that font 4 *must* be
194 a fixed-pitch font), and <style> is a list of style attributes
195 (attributes can be seperated by commas). A style attribute is one
196 of 'roman', 'bold', 'italic', 'fixed' or 'symbolic', or a combination
197 made by combining attributes with hyphens, for example 'fixed-bold'. If
198 you don't specify a font with a given combination of style
199 attributes, Zoom will use font 1 (for normal text) or font 4 (for
200 fixed pitch text). You can work out font names with the aid of
201 xfontsel. The special font name 'font3' refers to the built-in
202 symbolic font.
203
204 Colours are defined using a list of values of the form (R, G,
205 B). There should be at least 8 colours, coresponding to the
206 Infocom colour scheme, and there can be up to 11 (corresponding
207 to the colour scheme allowed by various interpreter versions):
208
209 0 = black
210 1 = red
211 2 = green
212 3 = yellow
213 4 = blue
214 5 = magenta
215 6 = cyan
216 7 = white
217 (I prefer cream to white, but that's a matter of personal preference)
218 8 = light grey (amiga) dark grey (DOS)
219 9 = medium grey (amiga)
220 10 = dark grey (amiga)
221
222 Colour 0 is the first specified in the list, and the rest follow
223 in sequence.
224
225 size <n>, <m> sets the size of the display to (n x m)
226 characters. These characters are the size of the fixed-pitch font
227 (font 4). For a version 6 game, the graphics file can be specified
228 using a command like
229
230 resources "/home/me/infocom/zorkzero/ZORK0/ZORK0.blb"
231
232 Presently only Blorb graphics files are supported. While I'm aware
233 of Blorb 1.1, I am somewhat hesitant to include JPEG support until
234 the current patent unpleasentness is resolved.
235
236 Zoom will load sound effects, but won't really do anything with them
237 at the moment.
238
239 If Zoom is run without a game specified, it will try to look in the
240 directory specified by 'gamedir', and list all of the games it finds
241 in there (games are assumed to be in files with a .z? extension) as
242 a menu, giving a choice as to which one to run. 'savedir' gives the
243 default directory for saving and restoring files.
244
245 Each game can be specified with a block like this, or the block
246 can be omitted. If you do specify a block for a game, the options
247 there override the defaults. For example:
248
249 game "Planetfall (Solid Gold edition)" 10.880531
250
251 might have no options, so it runs as the default - but,
252
253 game "Beyond Zork" 47.870915, 49.870917, 51.870923, 57.871221
254 {
255 interpreter 5
256 revision Z
257
258 savedir "/home/me/zcode/beyond"
259 }
260
261 specifies that Beyond Zork requires a different intepreter number
262 and should save its games into '/home/me/zcode/beyond' by default
263 - note that you can also specify different colour schemes and
264 fonts here (with fonts you can give a partial specification, so
265 just adding, say, 'font 1 "-weird-font" roman' would cause Zoom to
266 use that font instead of the default font 1, but keep the defaults
267 for the rest)
268
269 An example .zoomrc file can be found in the source distribution as
270 'zoomrc'
271
272Xft problems
273============
274
275 XRender and Xft might well provide nice anti-aliased fonts, but
276 unfortunately, Xft doesn't provide any 'font not found' mechanism,
277 instead choosing a default font. When Xft is not setup, in particular
278 when there is no XftConfig file, this can result in the same font
279 being used for anything. The troubleshooting section of the manual
280 describes how to create an XftConfig file. The poor man's solution
281 is simply to specify 'antialias no' in .zoomrc.
282
283Zoom and Windows
284================
285
286 *** THE WINDOWS DRIVER IS DEAD ***
287
288 Feel free to volunteer to resurrect it...
289
290 This version of Zoom now supports windows through the mingw32 library
291 (and to a lesser extent with Borland's C compiler). The windows display
292 library is a complete rewrite, and uses the techniques I discussed in
293 an raif posting to allow the window to be resized while a game is running.
294 These techniques are not without their penalty, however, and this version
295 of Zoom cannot be compiled with v6 support, and tends to redraw some
296 displays much slower than the X version. It also starts v3 games in the
297 top left of the screen instead of the bottom left, which is strictly
298 speaking against the standard, but saves me some fiddling.
299
300 The zoomrc has the format as described above. A windows font is described
301 using a string such as:
302
303 'Arial' 10 b
304
305 Which is Arial, 10pt, bold. The font name MUST be in single quotes ('). The
306 optional specifiers at the end can be left out entirely, or can be a
307 combination of:
308
309 b - bold
310 B - extra bold
311 i - italic
312 u - underline
313 f - fixed-pitch
314
315 The font specifiers in the example could then be:
316
317 font 1 "'Arial' 10" roman
318 font 2 "'Arial' 10 b" bold
319 font 3 "'Arial' 10 i" italic
320 font 4 "'Courier New' 10 f" fixed
321 font 5 "'Courier New' 10 fb" fixed-bold
322 font 6 "'Courier New' 10 fi" fixed-italic
323 font 7 "'Courier New' 10 fbi" fixed-bold-italic
324 font 8 "'Arial' bi" bold-italic
325 font 9 "font3" symbolic
326
327 (Note that the special font name 'font3' still specifies the built-in
328 version of font 3)
329
330Zoom and Mac OS X
331=================
332
333 This has been variously fixed and updated, along with everything else.
334 The Quartz renderer is to be preferred, for the higher-quality
335 rendering and best support for Unicode. Version 6 games (and blorb)
336 are supported in this port: images are *always* rendered using
337 Quartz.
338
339Why it goes fast
340================
341
342 Specialisation is a formal name for an optimisation strategy that
343 removes layers of interpretation from a program. A classic example
344 is the standard C printf statement:
345
346 printf("Foo %i bar %s baz\n", i, s);
347
348 The usual technique is for the runtime system to parse the string
349 and insert the values of i and s appropriately. A specialised
350 version of this statement would note that the format string is
351 /constant/, and never changes, so a specialised version of that
352 printf statement would evaluate the format string at compile time
353 and output simpler routines that just print 'Foo ', then i, then '
354 bar ', followed by s and ' baz\n'.
355
356 Zoom's particular specialisation is to note that many of the
357 bytecodes can only appear in limited combinations, so instead of
358 testing for the opcodes and then working out what the various bits
359 mean, Zoom simply tests for all possible values in an enormous
360 switch statement (or three) - this process is applied to the
361 opcodes themselves and their arguments. In addition, various
362 opcodes can be 'branch' opcodes or 'store' opcodes, etc. A custom
363 decoding routine is written for each and every opcode.
364
365 This would obviously take rather a long time to do by hand, but the
366 code is actually generated automatically by a helper program
367 (general purpose programs like this are known as 'partial
368 evaluators', but I'm not sure if the name applies to helper
369 programs such as the one used here). The code has to be generated
370 individually for different ZCode versions, and a consequence of
371 this is the rather large size of the Zoom executable (it's strongly
372 recommended you strip it to get rid of the excessively large
373 debugging tables :-)
374
375 Note that Zoom also makes extensive use of function inlining
376 (supported in C by gcc) to give an extra speed boost (actually
377 only an extra few %). If you compile in support for many Z-Code
378 versions, you may find that turning it off (by uncommenting the
379 '#define inline' in interp.c) will decrease the executable size
380 somewhat - as a side note, Zoom also depends on the compiler having
381 a few sensible optimisation strategies for its speed. Turning
382 optimisation off is probably never a good idea, as (under gcc under
383 x86 Linux) that increases the size of the executable and gives
384 quite a performance hit on those switch statements.
385
386 That's actually about it. Zoom is probably actually slower than
387 frotz in a few areas, I'll get round to writing a few benchmarks to
388 check them out and see what can be improved.
389
390Z-Machine extensions
391====================
392
393 Zoom provides a selection of extensions to the Z-Machine:
394
395start_timer (EXT:128) (no arguments, neither branch nor store)
396 This makes a note of the time this instruction is used. Normally this
397 will be the CPU clock time returned by clock().
398
399stop_timer (EXT:129)
400 This makes a note of the time this instruction is used, storing it
401 seperately from the time marked by start_timer.
402
403read_timer (EXT:130) (store)
404 This stores the difference between the start time and end time, as
405 defined by using the instruction above, in the variable. This time is
406 in centiseconds.
407
408print_timer (EXT:131)
409 This displays the difference between the start time and end time as a
410 decimal number of seconds, to centisecond precision.
411
412 If you want to add your own extensions for some nefarious purpose, all
413 opcodes are defined in src/zcode.ops, with definitions like:
414
415OPCODE "print_unicode" EXT:0x0b ARGS:1 VERSION 5,7,8
416%{
417 stream_printc(argblock.arg[0]);
418%}
419
420 Extended ops are only available in v4+ games and the Z-Machine
421 specification suggests that you only use extended opcodes that are greater
422 than 0x80 to add new instructions.
423